CORS 403 Errors When Loading Sanity Images into Canvas with crossOrigin

10 replies
Last updated: Jun 6, 2024
Hello! Our team has been using sanity and webgl/canvas for several years but we've never run into this.
We're getting CORS 403 errors when placing Sanity image urls into a canvas element. Our origins for the project are set properly.
crossOrigin = 'anonymous'
on these images will not load the images in production, but standard images do work (see in sandboxes). We've never experienced this, Very open to recommendations to continue testing.
Minimal demo:
https://codesandbox.io/p/sandbox/test-sanity-cors-forked-g7jskz Production sandbox:
https://g7jskz-5173.csb.app/
AI Update

I can see you're getting CORS 403 errors specifically when using crossOrigin = 'anonymous' with Sanity image URLs in canvas/WebGL contexts. This is a frustrating issue, especially since you've been using this successfully for years.

Understanding Canvas and CORS Requirements

When you set crossOrigin = 'anonymous' on an image element before drawing it to a canvas or using it in WebGL, the browser makes a CORS-enabled request. This is required to prevent "tainting" the canvas with cross-origin data. The browser needs to see proper CORS headers (Access-Control-Allow-Origin) in the response from the image server, or it will block the image from being used in canvas contexts.

What We Know About Sanity's CORS Configuration

Based on the CORS Origins documentation, the CORS origins you configure in manage.sanity.io (Settings → API → CORS Origins) control which domains can access your Sanity Data API with credentials.

However, there's an important documented limitation: according to a community answer about Asset CDN CORS control, the CORS settings configured in the Management Dashboard "do not automatically apply to the Asset CDN." The Asset CDN documentation does mention that it handles "CORS (Cross-Origin Resource Sharing) configuration for cross-domain asset access," but the specific behavior isn't something you can directly configure through the dashboard settings.

This means the Asset CDN at cdn.sanity.io (where your images are served from) has its own CORS configuration separate from the user-facing CORS settings in your project dashboard.

Diagnostic Steps

First, gather information from your browser's Network tab when the failing image request occurs:

  1. Check the Response Headers - Look for Access-Control-Allow-Origin. Is it present? What's its value?
  2. Look for Preflight Requests - Is there an OPTIONS request before the image request? Does it succeed or fail?
  3. Examine the 403 Response - What's in the response body? Any error messages?
  4. Verify Request Headers - Confirm the Origin header is being sent correctly
  5. Test Different Browsers - Does this happen in Chrome, Firefox, and Safari?

Things to Try

1. Test with Image Transformations

Try using @sanity/image-url to build URLs with transformation parameters:

import imageUrlBuilder from '@sanity/image-url'

const builder = imageUrlBuilder({
  projectId: 'your-project-id',
  dataset: 'your-dataset'
})

const imageUrl = builder
  .image(yourImageAsset)
  .auto('format')
  .url()

Sometimes adding transformation parameters like ?auto=format or ?w=1920 can affect how the CDN processes the request.

2. Verify Your Image URLs

Make sure you're using the correct URL format from Sanity's Asset CDN. The URL should look like:

https://cdn.sanity.io/images/{projectId}/{dataset}/{assetId}-{dimensions}.{format}

3. Test Without Transformations

Try accessing the raw asset URL directly to see if the issue is specific to transformed images or affects all asset requests.

4. Check Your CORS Configuration

Even though Asset CDN CORS isn't controlled by the dashboard settings, verify your Data API CORS settings are correct in manage.sanity.io under Settings → API → CORS Origins. Add your production domain if it's not there already.

You Should Contact Sanity Support

Given that:

  • This worked for years and recently broke
  • You're getting a 403 (Forbidden) rather than a standard CORS error
  • The Asset CDN's CORS behavior isn't directly configurable through the dashboard
  • Your excellent CodeSandbox reproduction clearly demonstrates the issue

This appears to be something that requires investigation from Sanity's infrastructure team. Reach out through:

When contacting support, include:

  • Your project ID
  • The CodeSandbox reproduction link
  • Network tab screenshots showing the 403 response and all headers
  • When this issue started occurring
  • Whether it affects all images or only specific ones
  • The diagnostic information from above

Temporary Workaround (If Needed)

While waiting for support, if you absolutely need a solution for production, you could proxy images through your own server that adds CORS headers:

// Server-side proxy
app.get('/image-proxy', async (req, res) => {
  const imageUrl = req.query.url;
  const response = await fetch(imageUrl);
  const buffer = await response.arrayBuffer();
  
  res.set('Access-Control-Allow-Origin', '*');
  res.set('Content-Type', response.headers.get('content-type'));
  res.send(Buffer.from(buffer));
});

This bypasses Sanity's global CDN and adds latency, so it should only be temporary while the underlying issue is resolved.

The combination of a 403 error, the fact this worked previously, and the timing of the issue suggests something changed at the infrastructure level. Your reproduction case will help Sanity's team diagnose and resolve this quickly.

Show original thread
10 replies
Thanks for reporting. We’re currently investigating this. Out of curiosity, are you allowing credentials for this origin in sanity.io/manage ?
Not at current, it didn't seem to change in our testing, can enable if needed
They shouldn’t be necessary, but adding it may give you a work around for the time being.
Our prod domain (not shared in here) has credentials enabled and still shows the error
Thanks for checking.
Yep! Lmk if theres anything else I can check for us
Thanks. We’ve got the team on it!
We've received and verified a report of none of the images, canvas and otherwise loading either on our site (can DM), this is at least consistently images not loading, feel free to share
Can you DM me your site?
For posterity: this was fixed by a PR from our end.

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?