Upload external image URL to Sanity client without CORS issues

11 replies
Last updated: Apr 7, 2020
Is there an option to pass an external image url to the sanity client, and have it uploaded? I need to upload image from another service, from a react app, but can't because of CORS. And would like to not have to set up a microservice just to be able to do this. 🙂
AI Update

Unfortunately, the Sanity API doesn't support directly importing images from external URLs from the browser due to CORS restrictions, and there's no way to work around the browser's security model without setting up a server-side solution.

Here's what's happening: When you try to fetch an image from an external URL in a React app running in the browser, you'll hit CORS errors if that external service doesn't have the proper CORS headers set. Even if you try workarounds like loading the image into a canvas element, the browser's toBlob() method will throw a security error once you've loaded cross-origin data.

Solutions

1. Server-side approach (Node.js) - Most reliable

If you can run a simple Node.js script or serverless function, you can use client.assets.upload() to upload images from external URLs. Here's the pattern from the importing data guide:

const fetch = require('node-fetch')
const sanityClient = require('@sanity/client')

const client = sanityClient({
  projectId: 'your-project-id',
  dataset: 'your-dataset',
  token: 'your-write-token',
  useCdn: false
})

const imageUrl = 'https://example.com/image.jpg'

fetch(imageUrl)
  .then(res => res.buffer())
  .then(buffer => client.assets.upload('image', buffer))
  .then(assetDocument => {
    console.log('Uploaded!', assetDocument)
  })

This could be a simple serverless function (like a Vercel/Netlify function or AWS Lambda) that your React app calls.

2. Sanity Functions - Modern serverless approach

You could also use Sanity Functions, which provides serverless compute within Sanity itself. This would let you create an endpoint that handles the image upload without needing to set up external infrastructure.

3. Custom Asset Source - If images are from a specific service

If you're always importing from the same external service, you could implement a Custom Asset Source that handles the server-side fetching for you within the Studio interface.

Why this limitation exists

As confirmed in this community answer, the browser's same-origin policy prevents reading binary data from external URLs unless they explicitly allow it via CORS headers. This is a security feature you can't bypass from client-side code.

The good news is that a simple serverless function should be pretty lightweight to set up - you don't need a full microservice, just a single endpoint that proxies the image fetch and upload.

Show original thread
11 replies
you might have a look at this: Custom Asset Sources

https://www.sanity.io/docs/custom-asset-sources
Thanks, but I wan't Sanity to store all images. I just need to import them through js client side, from an external source.
ahh, sorry, misread before
think you’d have to set up an external service for that 😕
user M
is right, the Sanity API doesn't support importing images from an url and there's no working around the browser security model here.
Ok, thanks. 🙂
Can’t it be kinda done via canvas? If you scroll down to the asset examples here? https://www.sanity.io/docs/js-client
You would still need to read the binary data from the image at another origin, and I don't think the same origin policy will allow that unless CORS headers are set.
user Y
I tried to do that, but as soon as you load external data into the canvas, the
toBlob()
throws error.
Aha! Well, that’s probably actually a good thing. Seems like lambdas or some such is the way to go

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?