Comparison

corsproxy.dev vs cors.sh: an honest comparison

Both managed CORS proxies, both running on Cloudflare's edge, both with public source. Unlike most competitors on our wider comparison, we could actually go read cors.sh's code instead of just quoting their marketing page — so this one has receipts.

· ~5 min read

Disclosure: corsproxy.dev is our product. cors.sh figures come from their pricing page, homepage, and their own public source repo (specifically SPEC.md, which they describe as "the source of truth for how the service behaves") as of the date above.

At a glance

  cors.sh corsproxy.dev
Free tier10,000 requests, 5 GB / month500 requests / day (about 15,000 / month), 250 MB / day
Paid planPro $4/month — 500,000 requests, 500 GB, no hourly capPro $5/month — 20,000 requests/day (~600k/month), 10 GB/day
Auth modelKey is public by design; the browser's Origin header is the real authenticator for live_ keysAPI key is the secret; origin allowlist enforced separately per key
Rate limitingDurable Object, but only on test_ keys (30/10s); live_ keys have no short-window cap, only the monthly quotaDurable Object, atomic, on every request regardless of key type
Blocks private-network targets (SSRF)No — not in their documented request checks (origin, target allowlist, size, rate; no IP/network filtering listed)Yes — checked on the resolved IP of every connection, including redirects
Response size cap enforcement6 MB, checked via Content-Length; their own spec flags the no-Content-Length case as an open gap ("mid-stream cutoff when length absent ⛳")Enforced regardless of whether the upstream declares a length
Open source / self-hostYes, MIT — but a full monorepo (proxy worker + Next.js console + Stripe billing + Auth.js), designed to run as their own SaaS, not a drop-in self-hostYes, MIT — a single Go binary, one file, deploy anywhere with one command
Keep third-party API keys out of the browserNot offeredYes: managed upstream headers
Request URLproxy.cors.sh/<url> + x-cors-api-key headerapi.corsproxy.dev/proxy?url=URL&key=KEY

Where cors.sh is ahead

Where corsproxy.dev is ahead

SSRF protection isn't optional here

We read cors.sh's own SPEC.md — every request check they document is listed: origin pinning, per-key target allowlists, the 6 MB size cap, rate limiting. Private-network and internal-address filtering isn't on that list. That means, as documented, a live_ key with no allowedTargets restriction could be pointed at http://169.254.169.254/ or an internal service and the proxy would fetch it. corsproxy.dev checks every target against the private/internal ranges on the resolved IP of every connection, including redirects, so a DNS-rebinding attempt can't get around it either. See how a CORS proxy can be abused for the full argument.

Rate limiting that doesn't have a paid-tier gap

cors.sh's Durable Object rate limiter is scoped to test_ keys only — their spec is explicit that live_ keys (the ones actually used in production) skip the short-window limiter entirely and rely on the monthly quota alone. That's a deliberate latency tradeoff on their end, but it means a compromised or misconfigured live key has no per-second brake until it's burned through a much larger monthly allowance. Every corsproxy.dev request, on every plan, hits the same atomic per-account limiter.

Actually self-hostable

cors.sh's source being public is genuinely notable — most competitors on our wider list aren't open at all. But their repo is the whole product: a Next.js console, Stripe billing, Auth.js accounts, D1 and KV bindings, built to run their own SaaS rather than to be dropped onto someone else's infrastructure in five minutes. Our proxy is one Go file with no external service dependencies — go run main.go or a single Docker container, and you're done. Both are honest "yes, open source" answers; they're different distances from your infrastructure.

Managed upstream headers

If your frontend calls an API that needs a secret key, corsproxy.dev can attach it server-side per request so it never ships to the browser. cors.sh's model doesn't have an equivalent — see calling OpenAI, Notion, and Google Sheets without leaking your API key.

Switching between them

const target = 'https://api.example.com/data';

// cors.sh
fetch('https://proxy.cors.sh/' + target, {
  headers: { 'x-cors-api-key': 'live_YOUR_CORS_SH_KEY' }
});

// corsproxy.dev
fetch(`https://api.corsproxy.dev/proxy?url=${encodeURIComponent(target)}&key=YOUR_CORSPROXY_DEV_KEY`);

Note the different auth shape: cors.sh sends the key as a header with the target unencoded in the path; corsproxy.dev takes the target as a URL-encoded query parameter with the key alongside it (or as an X-API-Key header for server-side callers). Not a drop-in swap either direction — budget a few minutes to update the call site, not just the base URL.

Which one to pick

Try it

Get a free API key — 500 requests/day, no credit card.