CORS (Cross-Origin Resource Sharing) Guide
Complete CORS reference: preflight requests, Access-Control headers, credentials, wildcard policies, and common pitfalls.
Complete CORS reference: preflight requests, Access-Control headers, credentials, wildcard policies, and common pitfalls.
| Header | Direction | Description | Example | Notes |
|---|---|---|---|---|
| Access-Control-Allow-Origin | Response | Specifies which origins can access the resource | Access-Control-Allow-Origin: https://example.com OR * (wildcard) | Cannot use * with credentials; must echo specific origin for credentialed requests |
| Access-Control-Allow-Methods | Response (preflight) | Allowed HTTP methods for the resource | Access-Control-Allow-Methods: GET, POST, DELETE | Returned in response to OPTIONS preflight; list only what's actually supported |
| Access-Control-Allow-Headers | Response (preflight) | Allowed custom headers in requests | Access-Control-Allow-Headers: Content-Type, Authorization, X-Custom-Header | Must include all non-simple headers the client needs to send |
| Access-Control-Expose-Headers | Response | Headers the browser is allowed to expose to client-side code | Access-Control-Expose-Headers: X-Total-Count, X-Page-Count | By default, only Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma are exposed |
| Access-Control-Allow-Credentials | Response | Whether cookies/auth are included in cross-origin requests | Access-Control-Allow-Credentials: true | Requires Access-Control-Allow-Origin to be a specific origin (not *) |
| Access-Control-Max-Age | Response (preflight) | How long (seconds) preflight result can be cached | Access-Control-Max-Age: 86400 | Reduces preflight overhead; browsers cap this (Chrome: 2h, Firefox: 24h) |
| Origin | Request | Client sends the origin making the request | Origin: https://example.com | Sent with all CORS requests; server uses this to decide whether to allow |
| Access-Control-Request-Method | Request (preflight) | Method that will be used in the actual request | Access-Control-Request-Method: DELETE | Sent in OPTIONS preflight to ask server if method is allowed |
| Access-Control-Request-Headers | Request (preflight) | Headers that will be used in the actual request | Access-Control-Request-Headers: Content-Type, Authorization | Sent in OPTIONS preflight to ask server if headers are allowed |
| Mistake | Fix |
|---|---|
| Using * with credentials | Echo the specific Origin header value instead of * |
| Forgetting to handle OPTIONS method | Add OPTIONS handler that returns CORS headers for preflight |
| Not caching preflight responses | Add Access-Control-Max-Age to preflight responses |
| Exposing custom headers without Access-Control-Expose-Headers | Add Access-Control-Expose-Headers for any custom response headers client needs |
| Returning CORS headers on all responses including errors | Ensure CORS headers are present on 4xx/5xx responses too |
The static files are identical to what the API returns, but with no rate limit and no server round trip. Use the API when you want a query and a content type; use the files when you want to cache one document.
curl "https://yjtoon.com/api/dataset/http-cors-guide?format=toon"
const res = await fetch( "https://yjtoon.com/static-data/dataset/http-cors-guide.toon" ); const toon = await res.text();
Rate limit: 120 requests per minute per IP, no key and no signup. API reference →