CORS proxy for Webflow, Framer, and Bubble custom code
You can't add a server-side proxy in a page builder — there's no server to add it to. Here's exactly which parts of Webflow, Framer, and Bubble hit CORS at all, and the one-line fix that doesn't require leaving the platform.
First: figure out if you actually have a CORS problem
CORS is enforced by the browser, on JavaScript running in the browser. Not every feature in these tools runs client-side, so not everything hits it:
- Webflow — a
<script>in a Custom Code embed callingfetch()runs in the visitor's browser. CORS applies. - Framer — a Code Component or Custom Code override that calls an API client-side runs in the browser. CORS applies.
- Bubble — the built-in API Connector calls most APIs from Bubble's own server, not the visitor's browser. CORS does not apply there. It's specifically client-side JavaScript — a "Run Javascript" workflow action, or a plugin that executes in-browser — that hits it.
If you're getting a console error that says "blocked by CORS policy," you're in the client-side case. If an API call is silently failing with no CORS message in the console, the problem is something else — check the actual response first.
Webflow: Custom Code embed
<script>
const target = encodeURIComponent('https://api.example.com/data');
fetch(`https://api.corsproxy.dev/proxy?url=${target}&key=YOUR_CORSPROXY_KEY`)
.then(r => r.json())
.then(data => {
document.getElementById('result').textContent = data.value;
});
</script>
Add this in Page Settings → Custom Code, or in an Embed element on the page. Same code either way.
Framer: Code Component
import { useEffect, useState } from "react"
export default function ApiData() {
const [value, setValue] = useState(null)
useEffect(() => {
const target = encodeURIComponent("https://api.example.com/data")
fetch(`https://api.corsproxy.dev/proxy?url=${target}&key=YOUR_CORSPROXY_KEY`)
.then(r => r.json())
.then(data => setValue(data.value))
}, [])
return <div>{value ?? "Loading…"}</div>
}
Bubble: when you're running client-side JS
If a plugin or a "Run Javascript" action calls fetch() directly against a third-party API with no CORS headers, route it the same way:
const target = encodeURIComponent('https://api.example.com/data');
fetch(`https://api.corsproxy.dev/proxy?url=${target}&key=YOUR_CORSPROXY_KEY`)
.then(r => r.json())
.then(data => {
// write into a Bubble state or element here
});
For everything else in Bubble — the standard API Connector flow — you don't need this at all; it's already calling from the server.
Don't put third-party API keys in the browser
No-code custom code is publicly visible in page source — never hardcode a third-party secret (an OpenAI key, a private API token) into a Webflow or Framer embed the way you might in a private codebase. Use managed upstream headers instead: configure the third-party credential once on your corsproxy.dev API key, and the browser only ever sees your corsproxy.dev key, which is scoped to your allowed origins.
Try it
Get a free API key — 500 requests/day, no credit card, no server to stand up.