Geocoding — entry 075 of 80

ViaCep

Verified Jul 2026

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.

brazilpostal-codecepaddress-lookupfree
AuthenticationNone requiredCall it straight away — no key, no signup.
HTTPSSupportedTraffic is encrypted in transit.
CORSEnabledCallable directly from browser JavaScript.
PricingFreeNo paid tier — free for the documented use case.
FormatsJSON, XMLResponses can be requested as JSON or XML.

GreatAPIs Score

Score80out of 100
Authentication25/25No authentication required
Pricing20/20Free to use
Docs0/20No docs or spec available
Formats15/15Supports 2 response formats
Freshness20/20Verified within 6 months

Embed this badge

Scored 80 on greatapis.com
<a href="https://greatapis.com/api/viacep/"><img src="https://greatapis.com/badge/viacep.svg" alt="Scored 80 on greatapis.com"></a>

Auth quickstart

  1. 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.
Stored keyNo key stored

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/

200 application/json; charset=utf-8

{"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

Base URLhttps://viacep.com.br/ws

Gotchas & 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."