Our extension needs to communicate with our backend, but we keep hitting a CORS error in development, even when properly setting CORS headers as described in the docs: Shopify CORS Docs
What We’ve Tried
Setting Access-Control-Allow-Origin: * and other required CORS headers.
Explicitly allowing https://partners.shopify.dev and https://admin.shopify.com.
Checking our tunnel (using trycloudflared) to ensure requests are routed correctly.
Running everything in production—and surprisingly, it works perfectly there.
The Problem
While the extension works in production, we cannot properly debug and test in development due to the persistent CORS rejection from the trycloudflared tunnel.
Has anyone encountered this before?
Is there a workaround to make CORS behave correctly during local development?
Would love to hear any best practices or solutions you’ve used!
Just wanted to follow up on this issue—huge thanks to @Tommy_Gaudreau from the Slack Community for pointing me in the right direction!
After days of debugging and trying different CORS headers with no success, the fix turned out to be a simple tweak in vite.config.ts:
Solution: Enable CORS in Vite
Adding cors: true to the Vite server configuration resolved the issue:
ts
CopyEdit
export default defineConfig({
server: {
port: Number(process.env.PORT || 3000),
hmr: hmrConfig,
fs: {
// See https://vitejs.dev/config/server-options.html#server-fs-allow for more information
allow: ["app", "node_modules"],
},
cors: true, // ✅ This fixed the CORS issue in development
},
});
Recap of the Problem
For context, we were building a Shopify Admin UI Extension (TypeScript/Remix) and encountered persistent CORS errors only in development when trying to communicate with our backend via trycloudflared. Despite setting proper CORS headers, nothing seemed to work—until we explicitly enabled CORS in Vite’s server config.
Lessons Learned
Shopify’s local tunnel (trycloudflared) can behave differently from production.
Even if backend headers are correct, the local dev server may still block requests due to its own CORS settings.
If you’re using Vite for your frontend, double-check your vite.config.ts server settings.
Hope this helps someone avoid the time sink we went through!
Thanks for taking the time to reply back with the answer. CORS trips up so many developers and having the actual solution searchable in this community makes it so much easier to find the answer.
using cloudflare tunnel (https ://contract-tim-exactly-illustration.trycloudflare.com/api/my-proxy) directly works for me instead of the app proxy
My client in this case is calling app_proxy is customer account ext.
What headers are you using?
Edit:
as per shopify cust acc ext documentation
“UI extension requests made to the App Proxy of password protected shops is not supported. Extension requests come from a web worker which does not share the same session as the parent window.”
so how do we work with dev stores that are password protected?
For context, after noticing that downgrading vite fixed the issue, I opened a ticket on the vite GitHub and the answer I got was that it was an expected breaking change to improve security (even though it’s in a patch update). I was pointed at the doc describing the change and options to correct the issue, which included adding the cors option in the config.
So if you’re running an older project and you suddenly get cors errors that you didn’t get before, this is probably why. That was my case and it was so confusing to figure it out