Documentation
Use cors.dev.
Put https://proxy.cors.dev/ in front of any public HTTPS URL. Free requests need no key for GET and HEAD up to 1 MiB with a 10-second deadline. A Pro Connection adds write methods, custom headers and 6 MiB responses, and Auto routes existing fetch and XMLHttpRequest calls.
Usage guides
One script. Keep your requests.
Auto repairs supported cross-origin reads in your existing Fetch and async XHR calls. Load it before your application; keep using the API’s original URLs. No key needed for public GET/HEAD.
<script src="https://cors.dev/auto.js"></script>
<script src="/app.js"></script>Working calls stay native. An eligible failed read gets one proxy fallback inside the same call. Don’t add async: Auto needs to load first.
ESM & bundled applications
import { installAuto } from 'https://cors.dev/auto.mjs';
const auto = installAuto();
await import('./app.js');Run this from a type="module" bootstrap. Importing the module alone does not install Auto. Use the dynamic application import so its dependencies run after installation.
If your bundler does not support URL imports, download auto.mjs into your application and use a local import. Find the current pinned paths in auto.json. The bundles have no runtime library dependencies; current aliases update, pinned paths do not.
Managed writes & options
<script
src="https://cors.dev/auto.js"
data-key="YOUR_CONNECTION_KEY"
data-hosts="api.example.com"
></script>
<script src="/app.js"></script>Auto checks your Connection’s routing configuration before choosing a transport. Supported managed writes use the proxy once; other writes stay native. Mutations are never retried through a different transport. Explicit upstream credentials also require your exact data-hosts allowlist. For managed uploads, use fetch(url, { method, body }); inherited Request bodies stay native.
Use data-mode="proxy-first" for known broken APIs, or data-mode="proxy-only" to disable native rescue for eligible proxy requests. data-mode="native-only" keeps calls native. Add data-xhr="false" to leave XHR untouched, or data-cache="60" for eligible managed GET caching. Cache-pinned reads do not use native rescue; hits count.
Cookies, one-use reads & CSP
A fallback read can reach the API twice. For a one-use URL or a GET with side effects, use auto.nativeFetch(url) from the ESM handle, or CorsAuto.nativeFetch(url) with the script. Readable HTTP errors and application aborts do not trigger fallback.
Cookie-including calls, same-origin requests, synchronous XHR and unsupported requests stay native. Auto cannot borrow another site’s browser session. Proxy requests keep the free or managed size and 10-second limits. Auto Fetch verifies finite streams; XHR buffers the complete response before delivery. Long-lived SSE is not supported.
For CSP, allow https://cors.dev in script-src and https://proxy.cors.dev in connect-src, alongside your native API hosts. A locally bundled copy only needs its own script origin. Auto cannot override a blocked destination in your page’s policy.
Add the prefix. Fetch your data.
Put https://proxy.cors.dev/ before the full URL of any public HTTPS API.
https://proxy.cors.dev/https://your-api/path?query=valueconst upstream =
'https://jsonplaceholder.typicode.com/todos/1';
const response = await fetch(
`https://proxy.cors.dev/${upstream}`,
{ credentials: 'omit' },
);
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
const data = await response.json();Run this in your frontend, served over HTTP or HTTPS. Keep public query strings as they are; the path form needs no encoding. Handling errors?
Other accepted URL forms
Coming from corsproxy.io or allOrigins /raw? Swap the host to proxy.cors.dev, remove any key= and keep the call. These forms resolve to the same target as the path form:
/?url= and /raw?url= with the target plain or percent-encoded, and /?https://... with the bare target as the whole query.
The query must start with url= or the target itself, so a corsproxy.io key= in front is rejected with 400. Encoded targets are decoded once, and anything after an encoded target is ignored. There is no allOrigins /get JSON wrapper: /get?url= returns 400. Only HTTPS targets are accepted.
Free requests.
Public JSON, XML, HTML, CSV and other text APIs. Your paths and queries, not just our examples.
- Methods
- GET & HEAD
- Max response
- 1 MiB
- Total deadline
- 10 seconds
Featured providers
jsonplaceholder.typicode.comapi.github.comapi.open-meteo.com
GET /api/catalog returns the featured hosts as { hosts: string[] }, alongside availability and service limits. Any public HTTPS host works; these are hand-picked starting points.
- Destinations
- Public HTTPS endpoints on port 443. Redirects are followed automatically. No request bodies.
OPTIONSis handled locally. - Headers
Accept,If-None-MatchandIf-Modified-Sinceare forwarded. Your Connection key is not.- Credentials
- Public data only: no upstream tokens, passwords, authorization headers or cookies. Use
credentials: 'omit'. Common credential query parameters are rejected. Request privacy. - Responses
- Responses are checked completely before delivery. Auto Fetch can stream with completion verification. No shared cache or automatic upstream retries. Responses use
Cache-Control: no-store, no-transform.
Rate limits & usage
Anonymous: a shared free pool with fair-use limits per IP; requests wait briefly for a slot when it is busy, with no daily or monthly quota. Free accounts: 120 requests/minute and 5 concurrent requests, with no monthly quota.
Admitted requests count even if the upstream fails. Provider limits and service protection still apply. Respect Retry-After when present.
Coming from corsproxy.io or allOrigins? Swap the host and keep your ?url= calls; see the accepted URL forms and the corsproxy.io and allOrigins migration notes.
TRIAL & PRO
Connect your own API.
Check managed availability in your account. Free access is available now.
A Connection key unlocks write methods, custom headers, explicit Authorization and larger responses on your enabled hosts. The trial includes 1,000 requests total over 7 days. Pro includes 500,000 requests per monthly billing period for $5.
- Destinations
- Public HTTPS hostnames on port 443, enabled on your Connection. No IP literals, private networks or embedded URL credentials.
- Methods & size
GET,HEAD,POST,PUT,PATCHandDELETE. Up to 1 MiB per request body and 6 MiB per response, with a 10-second total deadline. Auto Fetch verifies uncached streams; XHR, ordinary proxy requests and cache-selected responses are buffered. No long-lived SSE or automatic upstream retries.- Headers
- Explicit
Authorization,Content-Typeand custom API headers are supported. Browser cookies and your Connection key are never forwarded. Hop-by-hop, browser identity and proxy-control headers are reserved. Usecredentials: 'omit'. - Secrets
- A browser-visible upstream token is not a secret. Keep private credentials in your own backend. Origin matching limits browser use of your Connection key, but scripted clients can forge an Origin header.
- Caching
- Opt in on eligible
GETrequests withX-Cors-Cache: 60, where the value is a whole number of seconds from 1 to 300. Credential-bearing requests and private responses are not cached. Caching is best-effort, not a freshness or hit guarantee; cache hits still count toward your allowance. - Extra requests
- When paid checkout is available, Pro accounts can prepay $5 for 500,000 extra requests, plus tax where applicable. Extras are used after the base allowance; unused extras carry over across renewals but require an active Pro subscription. No automatic purchases.
- Rate & concurrency
- Pro: 600 requests per minute and 10 concurrent requests per account. Trial: 120 per minute and 5 concurrent requests. Shared service capacity and upstream limits also apply.
- Usage
- Admitted requests count even if the upstream fails. The trial allowance is total, not daily. Pro resets on its billing period, not the calendar month. Rotating a key does not reset usage.
OPTIONAL
Give your project a Connection.
Save exact browser origins and API hosts in your dashboard, then add the Connection’s publishable key to your request.
const upstream =
'https://jsonplaceholder.typicode.com/todos/1';
const response = await fetch(
`https://proxy.cors.dev/${upstream}`,
{
headers: { 'X-Cors-Key': 'YOUR_CONNECTION_KEY' },
credentials: 'omit',
},
);Origins, keys & account activity
Origins include the scheme and port, such as http://localhost:5173. Your key is a frontend identifier, not a secret. Keep it in the X-Cors-Key header, never in the URL. It is not forwarded upstream.
Activity starts with new keyed requests. Earlier anonymous requests are not added to your account history. Anonymous access works without signing in.
Create a free account or sign in with Google.
Find out what happened.
Supported upstream statuses and bodies are preserved. Check X-Cors-Source to see where a response came from.
upstream- The API answered, including its own 404 or 429 responses.
gateway- cors.dev rejected or couldn’t complete the request.
Error-handling example
const upstream =
'https://jsonplaceholder.typicode.com/todos/1';
const response = await fetch(
`https://proxy.cors.dev/${upstream}`,
{
credentials: 'omit',
},
);
if (!response.ok) {
const code = response.headers.get('X-Cors-Error');
const id = response.headers.get('X-Cors-Request-Id');
throw new Error(
`HTTP ${response.status}: ${code ?? 'upstream error'} (${id})`,
);
}
const data = await response.json();The request is malformed
invalid_requestPut the full public HTTPS URL after https://proxy.cors.dev/ or pass it as ?url=, the first query parameter. Targets cannot include credentials, a fragment or a port other than 443. Anonymous requests cannot carry credential-like query names such as key or token; trial and Pro Connections can.
The key or origin is rejected
invalid_key / origin_not_allowedFor a keyed Connection, check X-Cors-Key and the allowed origins in your dashboard. The page’s scheme, hostname and port must match exactly. Anonymous requests need no key and also work from file: pages; keyed requests need a page served over HTTP or HTTPS.
The method or header needs Pro
method_not_allowed / header_not_allowedFree requests send GET or HEAD with Accept, If-None-Match and If-Modified-Since only. Remove other headers, or use a trial or Pro Connection for POST, PUT, PATCH, DELETE, Authorization and custom headers. The error body links to the trial in its upgrade field.
The request body is too large
request_too_largeTrial and Pro requests accept request bodies up to 1 MiB. Send a smaller body.
The API host is not allowed
target_not_allowedAnonymous and free requests cover any public HTTPS host on port 443. For keyed requests, enable the exact host on your Connection, including redirect hops. Private destinations and IP literals are rejected.
The site owner has blocked proxy access
owner_opted_out / HTTP 403The domain owner has verified an opt-out. Requests to the blocked domain and its subdomains are refused on both the free and managed proxy. Your Connection settings and keys are unchanged. About domain opt-outs.
A request returns 429
rate_limited / quota_exceededRespect Retry-After when present. Anonymous requests share a free pool and wait briefly for a slot when it is busy; a 429 means the pool stayed full or a per-IP fair-use limit tripped. Check the dashboard for managed usage: the trial has 1,000 total requests and Pro has 500,000 per billing period. Upstream APIs and service protections also apply.
The API cannot be reached or redirects too often
upstream_unreachableThe upstream could not be connected to safely, or its redirect chain exceeded the automatic follow limit of 4 hops. Check the API is publicly reachable over HTTPS, shorten the chain, or use the final approved HTTPS destination.
A write request is redirected to another host
redirect_not_supportedManaged requests do not resend a request body to a different host. Send the request to the final HTTPS URL.
The response cannot be delivered
response_too_large / upstream_timeout / unsupported_responseChoose a smaller or faster endpoint. The response limit is 1 MiB for free requests and 6 MiB for managed trial and Pro requests. The total deadline is 10 seconds. Free requests accept text-based responses such as JSON, XML, HTML, CSV, JavaScript and SVG; trial and Pro accept any type, including images. Event streams such as text/event-stream and application/x-ndjson are only delivered through Auto Fetch.
The service is unavailable
service_unavailableThe proxy may be disabled or unable to coordinate requests. Contact us with the request ID, error code and time. Leave out project keys, response bodies and destination query strings.
A browser CORS error with no readable response can also come from connectivity or edge protection. A successful curl request alone does not verify your browser integration.