Como eu resolvi o limite de 10 anos da API do Banco Central do Brasil com Python

Published: (February 20, 2026 at 01:56 PM EST)
6 min read
Source: Dev.to

Source: Dev.to

O problema em detalhes

A API SGS do Banco Central é pública e gratuita. Você faz uma requisição HTTP com o código da série, data inicial e data final, e recebe um JSON com os valores.

Até 2025, era possível consultar qualquer período:

GET https://api.bcb.gov.br/dados/serie/bcdata.sgs.1/dados?formato=json&dataInicial=01/01/1984&dataFinal=31/12/2025

A partir de 2025, se o intervalo for maior que 10 anos, a API devolve erro 400 ou uma resposta vazia. Para obter a cotação completa do Dólar (código 1), que existe desde 1984, seria necessário fazer ao menos 5 requisições separadas, concatenar os resultados e remover duplicatas.

É exatamente isso que o BacenData automatiza.


A solução: paginação automática

pip install bacendata
from bacendata import sgs

# Série completa do Dólar — 40+ anos em uma chamada
dolar = sgs.get("dolar", start="1984-01-01")
print(f"{len(dolar)} registros de {dolar.index[0]} a {dolar.index[-1]}")

Como funciona por dentro

EtapaO que acontece
Calcula os intervalosDivide o período solicitado em chunks de no máximo 10 anos
Requisições paralelasUsa asyncio.gather com um Semaphore(5) para limitar a 5 requisições simultâneas (cortesia ao servidor do BACEN)
Combina os resultadosConcatena todos os DataFrames, remove duplicatas de datas sobrepostas e ordena cronologicamente
Trata erros individuaisSe um intervalo retornar 404 (dados não disponíveis), ele é ignorado sem abortar a consulta inteira

O resultado é um pandas.DataFrame limpo, pronto para análise.


Funcionalidades principais

1️⃣ Aliases para séries populares

Em vez de decorar códigos numéricos, use nomes:

# Estes são equivalentes
sgs.get(1, start="2020-01-01")
sgs.get("dolar", start="2020-01-01")

O BacenData vem com 14 séries pré‑configuradas:

AliasCódigoDescrição
selic11Taxa Selic diária
selic_meta432Meta Selic definida pelo Copom
selic_mensal4390Selic acumulada no mês
ipca433IPCA variação mensal
dolar1Dólar PTAX venda
euro21619Euro PTAX compra
cdi12CDI diário
igpm189IGP‑M variação mensal
juros_pf20714Taxa média de juros PF
juros_pj20715Taxa média de juros PJ
inadimplencia_pf21112Inadimplência PF
inadimplencia_pj21113Inadimplência PJ
reservas13621Reservas internacionais (USD)
focus_ipca13522Expectativa Focus IPCA

2️⃣ Múltiplas séries de uma vez

df = sgs.get(
    {"Selic": 11, "IPCA": 433, "Dólar": 1},
    start="2015-01-01"
)
print(df.head())

Resultado

                Selic   IPCA  Dólar
data
2015-01-02  0.046189    NaN  2.694
2015-01-05  0.046189    NaN  2.702
...

3️⃣ Últimos N valores

# Últimos 12 valores do IPCA
ipca = sgs.get("ipca", last=12)

4️⃣ Cache inteligente

O BacenData mantém um cache SQLite local com TTL automático por tipo de série:

PeriodicidadeTTL
Séries diárias6 horas
Séries mensais24 horas
# Desativar cache se necessário
from bacendata.wrapper.cache import desativar
desativar()

5️⃣ Metadados das séries

meta = sgs.metadata(1)
print(meta)
# {'codigo': 1,
#  'nome': 'Taxa de câmbio - Livre - Dólar americano (venda) - diário',
#  'periodicidade': 'D',
#  'unidade': 'u.m.c./US$', ...}

Arquitetura interna

bacendata/
├── wrapper/
│   ├── bacen_sgs.py    # Core: get(), aget(), metadata()
│   ├── catalogo.py     # 14 séries pré‑configuradas
│   ├── cache.py        # Cache SQLite com TTL
│   └── exceptions.py   # Exceções customizadas
├── api/
│   ├── app.py          # FastAPI app factory
│   └── routes/         # Endpoints REST
└── schemas/
    └── series.py       # Pydantic models

Paginação em detalhe

O coração do BacenData é a função _buscar_com_paginacao:

async def _buscar_com_paginacao(codigo, inicio, fim, client):
    intervalos = _gerar_intervalos(inicio, fim, max_anos=10)
    semaforo = asyncio.Semaphore(5)

    async def fetch_com_semaforo(ini, fi):
        async with semaforo:
            try:
                return await _buscar_serie_periodo(codigo, ini, fi, client)
            except (SerieNaoEncontrada, BacenAPIError):
                return []  # Intervalo sem dados, não aborta

    tasks = [fetch_com_semaforo(ini, fi) for ini, fi in intervalos]
    resultados = await asyncio.gather(*tasks)

    todos_dados = [item for sublista in resultados for item in sublista]
    if not todos_dados:
        raise SerieNaoEncontrada(codigo)
    return todos_dados
  • Semaphore(5) garante que nunca haja mais de 5 conexões paralelas, evitando sobrecarga no servidor do BACEN.
  • Cada intervalo é tratado de forma independente; falhas em um intervalo não abortam a consulta completa.

Com o BacenData, você obtém dados históricos completos do Banco Central de forma simples, rápida e segura, sem precisar se preocupar com a limitação de 10 anos da API oficial. 🚀

# BacenData – Biblioteca Python para Dados do Banco Central

## Problema resolvido

O `fetch_com_semaforo` resolve outro problema sutil: quando o usuário pede **“todos os dados disponíveis”**, o BacenData gera intervalos desde 1960. Para séries que começaram em 1984, os intervalos de `1960‑1970` e `1970‑1980` retornam **404**. Sem o `try/except`, o `asyncio.gather` falharia inteiramente.

---

## Stack técnica

- **httpx** (async) – cliente HTTP escolhido por suporte nativo a async, ao contrário do `requests`.
- **asyncio** – paralelismo de I/O para paginação.
- **pandas** – retorno em `DataFrame` para integração fácil com o ecossistema Python de dados.
- **SQLite** – cache local leve, sem dependências extras.
- **FastAPI** – API REST com docs automáticas (Swagger/ReDoc).
- **Streamlit + Plotly** – dashboard interativo para não‑programadores.

---

## API REST

O BacenData também expõe uma API REST para integração com qualquer linguagem/sistema:

```bash
# Instalar
pip install bacendata[api]

# Rodar
uvicorn bacendata.api.app:create_app --factory --port 8000

Endpoints

GET  /api/v1/series/{codigo}?start=2020-01-01&end=2025-01-01
GET  /api/v1/series/{codigo}/metadata
POST /api/v1/series/bulk          # múltiplas séries
GET  /api/v1/catalogo
GET  /api/v1/catalogo/search?q=selic
GET  /health

Exemplo

curl "http://localhost:8000/api/v1/series/1?start=2025-01-01&last=5"
{
  "codigo": 1,
  "nome": "Taxa de câmbio - Livre - Dólar americano (venda) - diário",
  "dados": [
    {"data": "2025-01-02", "valor": 6.1797},
    {"data": "2025-01-03", "valor": 6.1627},
    ...
  ],
  "total_registros": 5
}

Dashboard interativo

Para quem não programa, o BacenData tem um dashboard público em Streamlit:

https://bacendata.streamlit.app

Features

  • Gráficos interativos com zoom e hover
  • Comparação lado a lado de até 3 séries
  • Média móvel configurável
  • Download CSV/Excel
  • Todos os 14 indicadores disponíveis

Como contribuir

O projeto é open source (MIT). Algumas ideias para contribuição:

  • Adicionar novas séries ao catálogo
  • Integrar com a API de expectativas Focus (séries futuras)
  • Criar wrappers para R ou JavaScript
  • Melhorar a documentação

  • GitHub:
  • PyPI:
  • Dashboard:
  • Site:

Se você trabalha com dados econômicos no Brasil — como economista, analista, desenvolvedor ou pesquisador — o BacenData pode te poupar horas de trabalho manual. Dá uma olhada e me conta o que achou.

0 views
Back to Blog

Related posts

Read more »