Fixing CORS errors with a free proxy
In short: send your request to
/v1/proxy?quest=<encoded URL> instead of the target host. FreeTools fetches it
server-side and returns it with CORS headers, so the browser accepts the response.
"Access to fetch at ... from origin ... has been blocked by CORS policy" is one of the most common errors in front-end development, and one of the most misunderstood. CORS is not a bug in your code and it is not something the client can bypass. It is the server declining to allow another origin to read its response.
Why the error happens
When JavaScript calls fetch(), the browser sends a request and the target server
replies with headers. If those headers do not include
Access-Control-Allow-Origin naming your site, the browser discards the response
before your code ever sees it. The request still reached the server — the browser just refuses
to hand you the answer.
That is why the same URL works perfectly in cURL and fails in the browser. cURL does not enforce the same-origin policy.
The proxy approach
// fails: the API sends no CORS headers
await fetch('https://api.example.com/data')
// works: the proxy is same-origin for you, and it adds CORS headers
await fetch('https://freetools.one/v1/proxy?quest=' +
encodeURIComponent('https://api.example.com/data'))
URL-encode the target. If you interpolate the URL raw, any & in it will be
read as a separate query parameter and the request will be silently truncated.
When a proxy is the right answer
- You control the client but not the API, and the API will not add CORS headers.
- You are prototyping and cannot wait for the API owner to enable CORS.
- You need to reach a legacy internal endpoint from a one-off script.
When it is not
- Production traffic. You are adding a hop, a latency cost and a single point of failure to every request.
- Anything secret. A proxy sees the full request, including headers and cookies. Never send API keys or bearer tokens through a third-party proxy.
- When the API supports CORS. Most modern APIs do — check first.
Server-side proxying in Node
For anything you control, a two-line server route is safer than a public proxy, because credentials never leave your infrastructure:
app.get('/api/proxy', async (req, res) => {
const r = await fetch(req.query.url);
res.set('Access-Control-Allow-Origin', 'https://your-site.example');
res.json(await r.json());
});
Limits and safeguards
The FreeTools proxy caps responses at 5 MB and follows at most 5 redirects. More importantly, it resolves the hostname and rejects loopback, link-local, private and cloud metadata ranges — and it re-validates every redirect destination, so a public URL cannot be used to reach an internal service. That check is the whole point: an open proxy on the public internet is one of the most commonly abused server misconfigurations there is.
Diagnosing the error first
Before reaching for a proxy, it is worth confirming that CORS is really the problem. Open the browser developer console and look for the exact message:
- "blocked by CORS policy: No 'Access-Control-Allow-Origin' header" — the server did not allow your origin. A proxy helps.
- "preflight ... did not succeed" — the
OPTIONSrequest failed because the server does not handle preflight, or does not allow theAccess-Control-Request-Headersyou sent. - "net::ERR_FAILED" with no CORS message — usually a network, DNS or certificate problem, not CORS at all.
Only the first two are genuinely solved by a proxy. A DNS failure will fail identically through the proxy, and chasing it as a CORS problem wastes an afternoon.
Understanding preflight
Browsers send a OPTIONS request before the real call when the request is not
"simple" — anything with a custom header, a JSON content type, or a method other than
GET/HEAD/POST. The server must answer that preflight with the right
Access-Control-Allow-Methods and Access-Control-Allow-Headers. Many
servers are not configured for this at all, which is why adding
Content-Type: application/json can break a call that worked with form data.
Alternatives to a public proxy
| Approach | Effort | Use when |
|---|---|---|
| Server-side route you control | Low | Production, or anything with secrets |
| JSONP (legacy) | Very low | Old script tags only; effectively obsolete |
| Public CORS proxy | None | Prototyping, public data, throwaway scripts |
| Ask the API owner | One email | Anything that matters long-term |
What not to proxy
There is a short list of things that should never travel through a third-party proxy:
- API keys, bearer tokens and session cookies — the proxy can read all of them.
- Requests to internal services — which is exactly the SSRF the guard blocks.
- Anything regulated by data residency rules, where an extra hop changes the compliance story.
Rate limits
The FreeTools proxy sits behind a 30 requests per minute per IP limit and a 5 MB response cap. Those limits apply to the proxied response, so a large file will fail with HTTP 413 even though the upstream URL itself is perfectly valid. If you need to move bigger payloads, fetch them server-side and store them yourself.
Frequently asked questions
How do I bypass a CORS error in JavaScript?
Route the request through a CORS proxy: call https://freetools.one/v1/proxy?quest=<URL-encoded target>. The proxy fetches the target server-side and returns a response with CORS headers your browser accepts.
Why does my API work in cURL but fail in the browser?
cURL does not enforce the same-origin policy, but browsers do. The browser only exposes a cross-origin response if the server sends Access-Control-Allow-Origin, which is why the identical URL behaves differently in each.
Is a public CORS proxy safe to use?
Only for public, non-sensitive requests. The proxy can see everything you send through it, so never send API keys, cookies or bearer tokens. For production, proxy from your own server instead.
Does the FreeTools proxy protect against SSRF?
Yes. It resolves each hostname and blocks loopback, link-local, private and cloud metadata addresses, and it repeats the check on every redirect hop so a public URL cannot bounce to an internal service.