Issue Nº 34 — Sep 16, 2026

One 404 carries a CORS header. The other 404, right next to it, does not

Issue thirty-four covers TVmaze, the keyless JSON API for TV show and episode data. This session queried it live. A request for a show ID that does not exist returns a 404 that any browser script can read. A request for a route that does not exist returns a different 404, with no such header, so the same script cannot read it. The documented rate limit did not trigger once across thirty rapid calls.

Two 404s, one readable cross-origin, one not

GET /shows/999999, queried live this session, returned 404 with the body {"name":"Not Found","message":"","code":0,"status":404} and an access-control-allow-origin: * header.

GET /nosuchpath, queried live this session with the same Origin header, returned a different 404 body: {"name":"Not Found","message":"Page not found.","code":0,"status":404,"previous":{"name":"Invalid Route","message":"Unable to resolve the request \"nosuchpath\".","code":0}}. This response carried no access-control-allow-origin header at all, on two separate probes.

The practical effect: a browser script running on another domain can read the first error body directly, because the wildcard header lets it. The same script cannot read the second error body; the browser blocks it before the script sees a byte, even though the server sent one. A missing show ID and a missing route both fail with status 404, but only one of those failures is visible to cross-origin JavaScript.

Thirty rapid calls, no rate limit hit

The catalogue entry records a documented limit of 20 requests per 10 seconds per IP. This session ran thirty sequential GET calls to /shows/1 with no delay between them. Every one returned 200, and none returned 429.

Every response, including all thirty of those calls, carried cache-control: public, max-age=3600. That header lets a client cache the same show for an hour, which would cut real request volume against the documented limit for any client that respects it.

As with open-library's issue ten, this is a report of what the live probe returned, not a claim that the limit does not exist. A different IP, a different time window, or a burst larger than thirty calls could still trigger it.

Show IDs are not sequential

GET /shows/17 returned 404 this session. GET /shows/16 and /shows/18, either side of it, both returned 200.

TVmaze's show IDs are database primary keys, not a dense counter reserved only for published shows. A caller that iterates IDs looking for a complete catalogue will hit gaps like this one and needs to treat a single missing ID as normal, not as a sign the whole range is broken.

TVMaze, by the numbers

Rendered live from the atlas entry
AuthenticationNone required
HTTPSSupported
CORSEnabled
PricingFreemium
FormatsJSON
Rate limit

20 requests per 10 seconds per IP

Key endpoints
  • GET/shows/{id}
  • GET/search/shows?q={query}
  • GET/schedule
tv-datafree-apino-authschedule-data

Sources

Facts checked Sep 2026