• Latest
  • Trending
  • All

CORS Debugger 2026: Preflight Tester, Header Diagnostic and nginx/Apache/Express Config Generator

June 14, 2026
ssh command cheatsheet

SSH Command Cheatsheet: Connect, Keys, scp, Tunnels (2026)

June 16, 2026
chmod-chown-cheatsheet

chmod and chown Cheatsheet: Linux Permissions, Decoded (2026)

June 16, 2026
systemctl-journalctl-cheatsheet

systemctl + journalctl Cheatsheet: Services and Logs (2026)

June 16, 2026
grep-cheatsheet

The grep Cheatsheet: Search a File, Search a Tree (2026)

June 16, 2026
rsync-cheatsheet

The rsync Cheatsheet: Mirror, Sync, Copy Over SSH (2026)

June 16, 2026
curl-cheatsheet

curl Cheatsheet: Download Files and Test APIs (2026)

June 16, 2026
iptables-vs-nftables-cheatsheet cheatsheet

iptables vs nftables: Linux Firewall Cheatsheet, Side by Side

June 16, 2026
nmcli-cheatsheet cheatsheet

nmcli Cheatsheet: Wi-Fi and Network Connections From the Linux Terminal

June 16, 2026
powershell-networking-cheatsheet cheatsheet

PowerShell Networking Cheatsheet: Test-NetConnection, IP, DNS (2026)

June 16, 2026
tar command cheatsheet

The tar Command Cheatsheet: Create, Extract, Stop Guessing (2026)

June 16, 2026
Linux find command cheatsheet

The find Command Cheatsheet: Every Recipe You Actually Use (2026)

June 15, 2026
Linux networking commands cheatsheet, ip and ss

Linux Networking Commands in 2026: the ip and ss Cheatsheet

June 15, 2026
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools
Tuesday, June 16, 2026
  • Login
People Are Geek
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools
No Result
View All Result
People Are Geek
No Result
View All Result
Home Developer Tools

CORS Debugger 2026: Preflight Tester, Header Diagnostic and nginx/Apache/Express Config Generator

by People Are Geek
June 14, 2026
in Developer Tools
0
0
SHARES
3
VIEWS
Share on FacebookShare on Twitter

CORS preflight tester, response header diagnostic and config generator for nginx, Apache, Express and FastAPI

CORS has dragged me out of bed at 2 a.m. A deploy ships. The console goes red. The front end just can’t reach the API anymore, and you’re squinting at a header at midnight. So I built this. Point it at a URL, say which origin’s doing the calling, and it pulls the real response headers, works out whether a preflight is even in play, then names the exact thing that’s broken and hands you config you can paste into your server. Your origins never leave the page.

Enter a target URL and a calling origin, then click “Debug CORS”.
Recommended dev gearWe may earn a commission, at no extra cost to you.
Mechanical KeyboardCheck price on Amazon →Usb C Docking StationCheck price on Amazon →Portable MonitorCheck price on Amazon →Clean Code BookCheck price on Amazon →

What CORS actually checks and where most teams trip

The mental model took me embarrassingly long to actually get. CORS decides whether a script on one origin gets to read a response from another origin. The browser is the only thing doing that deciding. Not your server, which honestly is the bit that confuses everyone. It’s why curl pulls the same URL down clean while the browser slams the door on you: same response, different referee. And here’s what bites people. CORS doesn’t stop the request from leaving. The browser fires it off, your server runs it, the response comes back, and only then does the browser hide that response from the JavaScript that asked. So by the time “blocked by CORS” lands in your console, whatever that request did to your server, it already did. Read that twice if you’re firing a DELETE.

Maybe it’s just the kind of bug I attract, but it lands on one of three culprits almost every time. The wildcard-plus-credentials trap first. I’ve watched genuinely sharp people lose an hour to it. Access-Control-Allow-Origin: * sitting next to Access-Control-Allow-Credentials: true is flat-out illegal per the spec, and every modern browser refuses it. Kill the star. Echo the actual requesting origin instead. Then the missing preflight handler. Any non-simple request (a PUT, a DELETE, a weird Content-Type, some custom header) fires an OPTIONS preflight before the real call, and your server has to answer it with the right Allow-Methods and Allow-Headers. Most frameworks won’t hand you that for free. You wire up a middleware, or a route. And the sneaky one, the cached preflight. Access-Control-Max-Age tells the browser to remember the preflight result, so you fix your config and absolutely nothing changes until that cache ages out, and you sit there wondering why the “fix” did nothing.

How the diagnostic works

The fetch goes through our own backend on purpose. If the browser did it, the browser would block the inspection too, and then we’d be debugging the debugger, which is nobody’s idea of a good afternoon. So with the real headers in hand, I run them against the actual CORS rules. The check knows a simple request (GET, HEAD, a form-encoded POST) from a non-simple one. With the first kind, all that matters is what comes back. With the second, a preflight has to pass on its own before the real request is even allowed out the door.

Every diagnostic names the exact spec rule it’s checking, then the header value it actually saw, then the value you’d need for the thing to work. It’s verbose on purpose. CORS bugs are almost always one tiny mismatch hiding among headers that are otherwise perfectly fine, so the whole point is making that mismatch impossible to scroll past.

The server config snippets and what they protect against

Pick whatever stack you’re on. nginx, Apache, Express, FastAPI, Django, the config I hand back keeps the same cautious shape regardless. It echoes the request origin, but only when that origin’s on an explicit allow-list. It sets Vary: Origin so a cache can’t hand one caller’s response to somebody else. It answers the OPTIONS preflight with a clean 204, and it stays nowhere near the wildcard. An allow-list is just the right default now, I think. If your server fields cross-origin calls from one or two front ends you actually own, it has no business returning *. Not even on the endpoints you mentally file as “public.” The wildcard I save for stuff that’s genuinely open and stateless. A font CDN. A public price ticker. The kind of API where everything that matters already sits in the URL.

Common CORS mistakes the tool detects

  • Wildcard with credentials: pair Allow-Origin: * with Allow-Credentials: true and the browser just bins the whole response. No warning. Gone.
  • Wrong protocol mismatch: your caller’s on HTTPS, the origin you allow-listed is HTTP. Or the reverse. To the spec, those are two different origins, end of discussion.
  • Port mismatch: localhost:3000 and localhost:3001 aren’t the same origin. This one nabs everybody at least once, usually with two dev servers running side by side.
  • Missing OPTIONS handler: the framework coughs up a 404 or a 405 on OPTIONS, so the preflight dies before your real request even gets a turn.
  • Header in request not in Allow-Headers: any custom header you send (Authorization, X-Custom-*) has to show up in the preflight’s Access-Control-Allow-Headers, or the whole thing tips over.
  • Trailing space or slash in Allow-Origin: https://app.example.com/ with that one trailing slash will not match Origin: https://app.example.com. The compare is byte-for-byte. And yeah, I’ve burned real time on a single stray slash.
  • Missing Vary: Origin: a CDN caches the response for whoever called first, then keeps serving that same stale Allow-Origin to everybody who comes after.

How to deploy CORS changes without breaking traffic

I’m warier with CORS changes than with most config tweaks. The reason is the check runs in the browser, so a bad header crashes nothing loudly. It just quietly breaks the slice of users whose browsers happen to enforce the exact rule you botched. Test in the one lenient browser and your own console stays clean while real people can’t load anything. So, a few habits. Ship to staging and run the same browser test you’d run in prod, because Safari gets weird at the edges in ways Chrome and Firefox don’t. Then watch your OPTIONS count in the access logs live as it rolls. A sudden spike, or a cliff, usually points at a preflight cache problem or a handler that’s asleep at the wheel. And keep Access-Control-Max-Age low while you’re rolling, 60 seconds-ish, so a regression is something you can yank back instead of waiting on every browser’s cache to age out. Stable for a while? Bump it back to 86400. Then you can stop staring at logs.

Frequently asked questions

Why does my CORS work in Postman but not in the browser?

Because Postman isn’t a browser, and the browser is the only thing that enforces CORS. A call working in Postman or curl tells you one thing: your server’s willing to answer it. About whether a browser will let your JavaScript read that result? Nothing. So test in a real browser. And throw Safari in if you care about iOS, since it’s the one that surprises you.

Should I use the wildcard for a public API?

Only if it’s genuinely public. No auth, no per-caller state, and you’re dead sure you’ll never send credentials. The moment you need a cookie or an Authorization header from the browser, that wildcard becomes a wall and you’re rewriting it as an allow-list regardless. So skip the future migration and just start with the allow-list. It’s the same amount of config either way, honestly.

What is the difference between a simple and a non-simple request?

A simple request is a GET, a HEAD, or a POST whose Content-Type is application/x-www-form-urlencoded, multipart/form-data, or text/plain, carrying nothing but standard headers. Cross that line anywhere (a PUT, a DELETE, a Content-Type of application/json, an Authorization header) and you’re non-simple, which means a preflight goes out first. The preflight’s the fussier of the two. So that’s usually exactly where it breaks.

Can I just put a CORS proxy in front of my API?

Poking around locally? Sure, knock yourself out. In production? Please don’t. A proxy buys you latency and a brand-new single point of failure, plus one more security boundary you now have to harden and babysit forever. Just fix the API server to send the right headers. It’s the same five lines of nginx you were about to write anyway, except this version is actually yours.

Does CORS apply to images and stylesheets?

Mostly no, and this one trips people up. Loading an image or a stylesheet from another origin just works. The same-origin policy only wakes up when a script tries to read the bytes, say pulling pixels off a canvas or poking at the CSSOM. The whole CORS dance is really about fetch and XMLHttpRequest, anything where script gets to read what came back. Slap a crossorigin attribute on a script tag and you opt into CORS semantics for module imports, which is its own little adventure.

My CORS is fine but I see “Failed to fetch” in the console, what now?

That bare “Failed to fetch” with zero detail is the browser being unhelpful on purpose. Nine times in ten it’s one of two things. Either the preflight got rejected outright (your server threw a 405 or a 500 on OPTIONS), or the connection never landed at all. DNS died. Mixed content got blocked. A firewall ate it. Open the Network tab and hunt for a red OPTIONS sitting right before the request that failed. That little red row is almost always the one.

Sources & further reading

  • MDN, CORS
  • RFC 6454, The Web Origin Concept

Related tools and resources

HTTP Headers Checker Developer Error Fix Hub Web App Security Audit Guide Redirect Checker JSON Formatter Regex Tester TLS Version Selector
ShareTweetPin
People Are Geek

People Are Geek

I'm Stephane, a network and systems engineer with over 15 years of hands-on experience on production infrastructure, virtualization (ESXi, Proxmox), networking, and self-hosting. Earlier in my career I built and ran a Linux resource site that became a well-known reference for sysadmins. Today I focus on cybersecurity, and I also work as a technical trainer, teaching networking and security to people who do it for a living. Everything on People Are Geek comes from real-world practice, not theory. I build every tool on this site myself, and I write about what I've actually deployed, broken, and fixed. If it's here, I've used it.

People Are Geek

Copyright © 2017 JNews.

Navigate Site

  • About PeopleAreGeek
  • Affiliate Disclosure
  • All Tools and Articles
  • Contact
  • Cookie Policy
  • Hyper-V Hub: Tools, Error Fixes and Lab Guides
  • Linux Hub: Cross-Distro Reference, Articles, Tools
  • Privacy Policy
  • Sample Page
  • Terms of Service
  • VMware vSphere & ESXi Hub: Tools, Error Fixes and Guides

Follow Us

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Online Tools
  • Network Tools
  • Developer Tools
  • Security Tools

Copyright © 2017 JNews.