Geocoding — entry 075 of 80
ViaCep
ViaCEP is a free, high-availability web service for looking up Brazilian postal codes (CEP): given an 8-digit CEP it returns street, neighborhood, city, state, and IBGE/DDD codes, with a reverse address-to-CEP search available too. It's run by WBX and widely embedded across Brazilian dev tooling — its own docs warn that heavy bulk-validation traffic against it can trigger an automatic, indefinite IP block.
ViaCEP is a free, high-performance lookup service for Brazilian postal codes (CEP) — its own docs call it a "webservice gratuito de alto desempenho": given an 8-digit CEP it returns street, neighborhood, city, state, and IBGE/DDD codes, with the response format chosen by URL path segment (`json`, `xml`, and the undocumented-but-working `piped`) rather than an `Accept` header or query parameter.
GreatAPIs Score
Auth quickstart
- No API key required — requests are public and keyless. ViaCEP's own docs warn that heavy bulk-validation traffic against it can trigger an automatic, indefinite IP block; no fixed requests-per-second number is published.
Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.
Look up a CEP as JSON
GEThttps://viacep.com.br/ws/01310100/json/
{"cep":"01310-100","logradouro":"Avenida Paulista","complemento":"de 612 a 1510 - lado par","unidade":"","bairro":"Bela Vista","localidade":"São Paulo","uf":"SP","estado":"São Paulo","regiao":"Sudeste","ibge":"3550308","gia":"1004","ddd":"11","siafi":"7107"}Developer reference
https://viacep.com.br/wsGotchas & limits
- A well-formed but unassigned CEP returns HTTP **200**, not an error status — a live probe of `/ws/99999999/json/` returned exactly `{"erro":"true"}` (confirmed byte-exact in this run): `erro` is a JSON *string* `"true"`, not a boolean, so a naive `if (response.erro)` check works by accident in JavaScript but a typed client expecting a boolean will misparse it.
- A malformed CEP (wrong length) fails completely differently: a live probe of `/ws/123/json/` returned HTTP **400** with a `text/html; charset=utf-8` body — a plain HTML error page, not JSON — so callers need to handle three distinct outcomes (200 real address, 200 `{"erro":"true"}`, 400 HTML) rather than a single error path.
- The response format is chosen by swapping the last path segment — `/ws/{cep}/json/`, `/xml/`, or `/piped/` — confirmed live: the same CEP returned a pipe-delimited single line under `/piped/` (`200 text/plain`) and a `<xmlcep>`-rooted document under `/xml/` (`200 application/xhtml+xml`), with identical field values to the JSON form. Only `json` and `xml` are documented ("deve ser `json` ou `xml`"); an unrecognised segment 400s with the same HTML error page as a malformed CEP, so don't guess at format names.
- JSONP is a query parameter on the `json` route, not its own path segment: `GET /ws/{cep}/json/?callback=meuCallback` returned the object wrapped as `meuCallback({...});` on a live probe, matching the docs' own JSONP example.
- Reverse lookup goes the other direction, by address rather than by coordinates: `GET /ws/{uf}/{cidade}/{logradouro}/json/` searches by state, city, and street name and returns an array of matching addresses, each with its own CEP — there's no lat/lon-based reverse geocoding endpoint.
- CORS is open on the 200 responses (`Access-Control-Allow-Origin: *`, including on the `{"erro":"true"}` body) but the 400 carries **no** `Access-Control-*` headers at all — both confirmed live. So a browser `fetch()` of a malformed CEP fails at the CORS layer with an opaque network error rather than a readable 400, which is exactly why ViaCEP's docs tell you to check the 8-digit format client-side before calling: "Antes de acessar o webservice, valide o formato do CEP e certifique-se que o mesmo possua {8} dígitos."