ANA/SNIRH — Agencia Nacional de Aguas¶
Visao Geral¶
| Item | Detalhe |
|---|---|
| Provedor | ANA (Agencia Nacional de Aguas e Saneamento Básico) |
| Dados | Hidrografia, pivos de irrigação, demanda de irrigação, disponibilidade hidrica, massas d'água |
| Acesso | ArcGIS REST MapServer API |
| Formato | JSON (tabular) / GeoJSON (geo) |
| Autenticação | Nenhuma |
| Licença | Dados publicos |
Layers¶
| Layer | Features | Geometria | bbox obrigatório |
|---|---|---|---|
hidrografia |
~620K polylines | Polyline | Sim |
pivos_irrigacao |
~19.9K polygons | Polygon | Não |
demanda_irrigacao |
~265K polygons | Polygon | Sim |
disponibilidade_hidrica |
~42K polylines | Polyline | Não |
massas_dagua |
~241K polygons | Polygon | uf ou bbox |
Epoca e referencia dos dados¶
pivos_irrigacao e pivos_irrigacao_geo usam o mapeamento de 2014,
produzido pela ANA em parceria com a Embrapa Milho e Sorgo, conforme os
metadados oficiais de Pivos_Mapeados.
Nas camadas de demanda e disponibilidade, versao preserva o campo oficial
DSVERSAO. O valor observado BHO 2013 versao 1.3 de 22/07/2014 identifica a
versão da base hidrografica; ele, sozinho, não determina o ano das estimativas
de demanda. As datas de consulta em MetaInfo, como fetched_at, indicam quando
os dados foram obtidos, não quando o levantamento foi realizado. Essas camadas
não representam medicoes hidrologicas em tempo real.
Acesso via ArcGIS REST¶
| Parâmetro | Valor |
|---|---|
| Base URL | https://portal1.snirh.gov.br/server/rest/services/dados_abertos |
| Serviço | MapServer/0 |
| Paginação | Por chave: orderByFields=OBJECTID e OBJECTID > ultimo (até 1K features/pagina) |
| Throttle | Pausa de 2s após a sexta página e as seguintes |
| Timeout de leitura | 180s |
A coleta exige OBJECTID em ordem crescente estrita dentro de cada página e
acima da última chave da página anterior. Chaves repetidas, sobrepostas ou
fora de ordem geram SourceUnavailableError.
As funções tabulares solicitam JSON com returnGeometry=false; as variantes
_geo solicitam GeoJSON e mantem a geometria em EPSG:4326. O filtro espacial
bbox e aplicado em ambas as modalidades.
As duas modalidades exigem todos os atributos pedidos em cada feicao. Um
atributo ausente gera ParseError, mesmo que esteja presente em outra
feicao da mesma página; um valor nulo declarado continua permitido.
Exemplo de Uso¶
import asyncio
from agrobr import ana
async def main():
# Hidrografia (bbox obrigatorio — dataset grande)
df = await ana.hidrografia(bbox=(-50, -20, -48, -18))
# Com geometria
gdf = await ana.hidrografia_geo(bbox=(-50, -20, -48, -18))
# Pivos de irrigacao
df = await ana.pivos_irrigacao(uf="GO")
# Pivos com geometria
gdf = await ana.pivos_irrigacao_geo(uf="SP", bbox=(-50, -22, -48, -20))
# Demanda de irrigacao (bbox obrigatorio)
df = await ana.demanda_irrigacao(bbox=(-50, -20, -48, -18))
# Disponibilidade hidrica
df = await ana.disponibilidade_hidrica(bbox=(-46, -20, -44, -18))
gdf = await ana.disponibilidade_hidrica_geo(bbox=(-46, -20, -44, -18))
# Com metadados
df, meta = await ana.pivos_irrigacao(return_meta=True)
# Polars
df = await ana.pivos_irrigacao(as_polars=True)
# Limitar features
df = await ana.hidrografia(bbox=(-50, -20, -48, -18), max_registros=500)
# Massas d'água (uf ou bbox obrigatório)
df = await ana.massas_dagua(uf="DF")
gdf = await ana.massas_dagua_geo(bbox=(-47.6, -16.0, -47.5, -15.9))
asyncio.run(main())
Colunas por Layer¶
hidrografia¶
| Coluna | Tipo | Descrição |
|---|---|---|
| OBJECTID | int | ID do registro |
| codigo_curso | str | Código do curso d'agua |
| codigo_bacia | str | Código da bacia |
| nome_rio | str | Nome do rio |
| dominio | str | Domínio |
pivos_irrigacao¶
| Coluna | Tipo | Descrição |
|---|---|---|
| OBJECTID | int | ID do registro |
| codigo_municipio | str | Código do município |
| municipio | str | Município |
| estado | str | Estado |
| regiao_hidro | str | Região hidrografica |
| area_ha | float | Area em hectares |
demanda_irrigacao¶
| Coluna | Tipo | Descrição |
|---|---|---|
| OBJECTID | int | ID do registro |
| ID | int | ID |
| codigo_bacia | str | Código da bacia |
| versao | str | Identificador original DSVERSAO da base hidrografica |
| vazao_max_mensal | float | Vazao de retirada máxima mensal (m3/s) |
| vazao_mes_seco | float | Vazao de retirada no mes seco (m3/s) |
| vazao_mes_irrigacao | float | Vazao de retirada no mes de irrigação (m3/s) |
| vazao_media_anual | float | Vazao de retirada media anual (m3/s) |
disponibilidade_hidrica¶
| Coluna | Tipo | Descrição |
|---|---|---|
| OBJECTID | int | ID do registro |
| ID | int | ID |
| area_montante_km2 | float | Area de montante em km2 |
| disponibilidade_m3_s | float | Disponibilidade em m3/segundo |
| nome_rio | str | Nome do rio |
| dominio | str | Domínio |
| versao | str | Identificador original DSVERSAO da base hidrografica |
Massas d'água¶
massas_dagua e massas_dagua_geo leem os polígonos de lagos, lagoas, reservatórios e trechos de rio representados
como polígono, do tema oficial "Massas d'Água" da ANA (versão 2019, escala 1:100.000, metadado no catálogo da ANA,
licença: "O acesso ao dado é livre."). A hidrografia é outra camada: só as linhas da drenagem (BHO), sem polígono.
| Item | Detalhe |
|---|---|
| Serviço | https://www.snirh.gov.br/arcgis/rest/services/SPR/Massa_dagua/MapServer/0 (o mesmo que o metadado aponta) |
| Feições | 240.899 polígonos (a contagem do shapefile nacional 2019) em 01/10/2026 |
| Volume | DF: 228 feições, ~0,9 MB de GeoJSON; RS: 33.467 feições, ~140 MB pela média do DF |
| Recorte obrigatório | uf ou bbox (o Brasil inteiro passa de 1 GB); os dois juntos = interseção |
uf: o camponmufetraz o nome da UF em maiúsculas, com acento, e lista as UFs de uma feição de divisa separadas por vírgula ("DISTRITO FEDERAL, GOIÁS"). O filtro casa o nome inteiro como item da lista:uf="MT"não pegaMATO GROSSO DO SUL, euf="DF"pega a feição de divisa. Na saída, a colunauftraz as siglas ("DF/GO"): quem filtra o resultado comdf["uf"] == "DF"perde as feições de divisa. 106 feições não têm UF e só saem porbbox. Nome fora do cadastro deixa aufda feição nula e vira aviso noMetaInfo.validation_warnings.- Paginação por faixa de
FID: este servidor recusaresultRecordCounteorderByFields("Pagination is not supported"). A consulta conta as feições, lê a lista oficial deFID(returnIdsOnly) e pede cada faixa de até 1.000FIDnowhere. A página tem de trazer exatamente osFIDda faixa; faltou algum, ou a lista não bate com a contagem, levantaSourceUnavailableError. Página ilegível, feição sem algum dos 19 campos pedidos (a fonte manda todos, nulos inclusive) ou geometria ilegível levantaParseError.max_registroscorta a lista deFID, em ordem crescente. - Valores publicados: a fonte publica texto vazio como
" "(sai nulo) e muitos numéricos ausentes como0(no DF, em 01/10/2026:volume_hm30 em 198 das 228 feições,codigo_snisbem 188 ecodigo_trechoem 222); os zeros são preservados. OFIDé a chave interna do serviço e não sai; o código oficial écodigo. - Fora da saída: o nome do empreendedor (
nmemp, que traz nome de pessoa física) não é pedido ao serviço. - O serviço
dados_abertos/Massa_d_Aguado portal das outras camadas respondia erro 500 em 01/10/2026; por isso o agrobr usa oSPR/Massa_dagua. O shapefile nacional do metadado (426 MB, sem divisão por UF) não é baixado.
| Coluna | Tipo | Campo da fonte | Descrição |
|---|---|---|---|
| codigo | Int64 | esp_cd |
Código da massa d'água |
| nome | str | nmoriginal |
Nome original |
| nome_alternativo | str | nmalternat |
Nome alternativo |
| tipo | str | detipomass |
Natural ou Artificial |
| dominio | str | dedominial |
Dominialidade (Federal ou Estadual), como na hidrografia |
| entidade_fiscalizadora | str | defiscaliz |
Entidade fiscalizadora |
| uso_principal | str | usoprinc |
Uso principal da água |
| volume_hm3 | float | nuvolumhm3 |
Capacidade de armazenamento (hm³) |
| area_km2 | float | nuareakm2 |
Área (km²) |
| area_ha | float | nuareaha |
Área (ha) |
| perimetro_km | float | nuperimkm |
Perímetro (km) |
| data_construcao | datetime | dtreserv |
Data de construção do reservatório (dd/mm/aaaa na fonte) |
| nome_rio | str | nmriocomp |
Nome do rio |
| codigo_snisb | Int64 | cod_snisb |
Código do SNISB |
| codigo_trecho | Int64 | cotrecho |
Código do trecho de drenagem da BHO |
| uf | str | nmufe |
Siglas das UFs, em ordem alfabética e separadas por / ("DF/GO") |
| municipios | str | nmmun |
Municípios, como publicados ("BRASÍLIA, FORMOSA") |
| fonte_geometria | str | deversao |
Origem da geometria (FBDS (2017), bho_massa_dagua_2019…) |
Particularidades¶
- bbox obrigatório:
hidrografiaedemanda_irrigacaorequerem bbox (datasets grandes) - Paginação por chave: cada página pede até 1K features ordenadas por
OBJECTIDe a seguinte continua do ultimoOBJECTIDrecebido, até completar a contagem oficial. O servidor da Hidrografia devolve uma feicao a menos que o pedido em cada página; com paginação por offset, a feicao da fronteira se perdia (1.046 de 1.047 no recorte de teste). Se a paginação parar antes da contagem oficial, ou se uma página não avancar oOBJECTID, a consulta levantaSourceUnavailableErrordizendo quantas feicoes faltam, em vez de devolver resultado parcial. Página ilegivel (JSON cortado, HTML de proxy) ou semOBJECTIDlevantaParseError - max_registros: inteiro positivo que limita as feições retornadas, ou
Nonepara não limitar. Zero, negativos, booleanos e valores não inteiros levantamInvalidParameterErrorantes da coleta. O argumento anteriormax_featuresnão é mais aceito. Quando a camada tem mais feições que o limite, a consulta emiteUserWarning("ANA hidrografia: retornadas 5 de 63 feições por limite local; restrinja filtros ou use max_registros=None."), põe a mesma frase emMetaInfo.validation_warningse publicasource_details["coverage"]comexpected_rows(total da camada),returned_rows,local_limitetruncated=True. O total é a contagem que a consulta já faz antes de baixar as páginas, a mesma que decide a coleta; não há contagem extra. Sem corte, o resultado e oMetaInfonão mudam - Campos obrigatórios: todo campo pedido ao serviço (
outFields) tem de vir em cada feição de cada página no tabular e em cada página nas variantes_geo. O serviço manda todos, nulos inclusive, então campo ausente é mudança de layout e levantaParseErrorcom o nome do campo, em vez de devolver a coluna a menos
| Layer | Campos pedidos |
|---|---|
hidrografia |
OBJECTID, COCURSODAG, COBACIA, NORIOCOMP, DEDOMINIAL |
pivos_irrigacao |
OBJECTID, CD_GEOCMU, NM_MUNICIP, NM_ESTADO, REGIAO_HID, HECTARES |
demanda_irrigacao |
OBJECTID, ID, COBACIA, DSVERSAO, VZMAXMEN, VZMESSEC, VZMESIRR, VZMEDANO |
disponibilidade_hidrica |
OBJECTID, ID, NUAREAMONT, DISPQ95, NMRIO, DEDOMINIAL, DSVERSAO |
massas_dagua |
FID e os 18 campos da tabela de colunas das massas d'água (o FID não sai) |
Contagem oficial zero devolve um resultado vazio válido, com as colunas publicadas;
nas variantes _geo, o resultado vazio também sai em EPSG:4326. A presença
de um campo com valor nulo e diferente da ausência desse campo; valores nulos e
zeros são preservados.
OBJECTID e ID mantêm os nomes da fonte e usam Int64 anulável. Medidas usam float64; códigos textuais preservam o texto publicado. O texto usa o dtype nativo do pandas (str no pandas 3, object no pandas 2), e os resultados vazios têm os mesmos dtypes dos resultados com registros.
Limitacoes¶
- Hidrografia e demanda de irrigação exigem bbox (sem filtro retornaria centenas de milhares de features)
- Apenas pivos e massas d'água oferecem filtro por UF; todas as camadas aceitam bbox e max_registros
- Não ha filtro de ano ou intervalo de datas; a consulta usa a edição de cada camada configurada
- A consulta conta os registros antes de baixar as páginas; mesmo um max_registros pequeno pode exigir aguardar essa contagem
- As páginas são acumuladas em memoria antes de construir o resultado; não ha streaming nem cache persistente ANA
- Pausa de 2s após a sexta página e as seguintes para não sobrecarregar o servidor
Coleta bruta¶
from agrobr import bruto
coleta = await bruto.coletar(
"ana", "massas_dagua", destino="dados", uf="DF",
bbox=(-47.466, -15.993, -47.462, -15.988),
bbox_crs="EPSG:4674", nome="barragem_df",
)
A coleta guarda os corpos Esri JSON sem renomear atributos, sem remover campos como gid e sem transformar as geometrias. Pede todos os atributos, geometria e outSR=4674; o CRS é conferido no corpo recebido. Os mesmos filtros e CRS de entrada são usados nas contagens, na lista oficial de FIDs e nas páginas. A ordenação dos FIDs serve para definir as faixas dos pedidos; a ordem e os bytes das feições recebidas são preservados. O recurso só fecha com contagens e FIDs concordantes. Zero feições exige duas contagens zero e a lista oficial vazia.
Veja a API da coleta bruta e o contrato do manifesto.
Proveniência de consultas com várias páginas¶
return_meta=True agora preenche raw_content_hash e raw_content_size também quando a ANA retorna mais de uma página. Nesse caso, o hash identifica a serialização UTF-8 de {"query": ..., "resources": ...}, com chaves ordenadas, ensure_ascii=False e separadores (',', ':'). raw_content_size mede essa serialização. O tamanho total dos corpos originais está em source_details["resource_bytes"].
source_details publica hash_kind="resource_manifest_sha256", manifest_encoding="canonical_json_utf8", manifest_fields=["query", "resources"], query e resources. A consulta lógica contém fonte, recurso, where, bbox, max_registros e formato; resources preserva a ordem da aquisição e contém pagina (a partir de 1), sha256 e bytes.
Uma única página conserva o hash e o tamanho do corpo; zero páginas conserva hash nulo e tamanho zero. Dados, colunas, tipos, geometrias, CRS, requisições e source_url das APIs tabulares/geográficas permanecem iguais. O manifesto de hashes do MetaInfo não armazena corpos; use a coleta bruta para preservá-los em disco.
Geometria inválida¶
A geometria das saídas _geo sai como a fonte publica, sem reparo; geometria inválida gera aviso e contagem no MetaInfo. Veja Geometrias publicadas.