Issue Nº 51 — Oct 3, 2026
A 404 from Postcodes.io can still carry data
Issue fifty-one covers Postcodes.io, a free, keyless UK postcode lookup in the Geocoding category. This session queried it live. A retired postcode returns a 404 with coordinates inside it. Three endpoints report a miss in three different ways. Two limits stop at 100.
A retired postcode is a 404 with data inside
This session sent GET https://api.postcodes.io/postcodes/E1W1UU. The API returned HTTP 404 and the error "Postcode not found". The body also held a terminated object: postcode "E1W 1UU", year_terminated 2015, month_terminated 2, and a longitude and latitude (-0.073706, 51.508009).
A postcode that never existed gets a plain 404. GET /postcodes/ZZ999ZZ returned {"status":404,"error":"Postcode not found"} with no terminated object.
A client that treats every 404 as "unknown postcode" loses the termination date. Check for the terminated key first. GET /terminated_postcodes/E1W1UU returned HTTP 200 with the same year and month, plus eastings and northings.
Three endpoints, three kinds of miss
A single lookup of a bad postcode returns HTTP 404. GET /postcodes/ZZ999ZZ/validate returned HTTP 200 and {"status":200,"result":false}. The same call for SW1A1AA returned {"status":200,"result":true}. The validate endpoint did not return a 404 in this session.
A bulk POST to /postcodes with {"postcodes":["ZZ99 9ZZ","SW1A 1AA"]} returned HTTP 200. The first row was {"query":"ZZ99 9ZZ","result":null}. The second row held the full record for SW1A 1AA.
So a bulk client must test each row for a null result. It cannot rely on the HTTP status.
Bulk lookup and list limits stop at 100
A bulk POST with 100 copies of SW1A 1AA returned HTTP 200 and 100 result rows. A POST with 101 returned HTTP 400. The message was "Too many postcodes submitted. Up to 100 postcodes can be bulk requested at a time".
The reverse lookup, GET /postcodes?lon=-0.141563&lat=51.50101, returned one postcode with the default radius. With radius=2000 it returned 10 postcodes, the farthest 217 m away. Adding limit=100 returned 100 postcodes. limit=101 also returned 100. The API did not return an error for the larger value.
The search call GET /postcodes?q=SW1A returned 10 results. With limit=101 it returned 100.
No key, and CORS is a wildcard
Every response probed in this session carried access-control-allow-origin: *. This includes 200 and 404 responses, the validate call, the bulk POST and GET /random/postcodes. No key or account header was sent.
A full record holds over 40 fields. They include admin_ward, lsoa21, icb, and both parliamentary_constituency and parliamentary_constituency_2024. For SW1A 1AA, the two constituency fields held the same name, Cities of London and Westminster.