Upload external image URL to Sanity client without CORS issues
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 thread11 replies
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.