bcbpy
Python client for the BCB SGS (Sistema Gerenciador de Series Temporais) API from the Banco Central do Brasil.
Fetch Brazilian economic and financial time series as pandas DataFrames with a simple, Pythonic interface. Includes 114 curated series codes covering exchange rates, interest rates, inflation, GDP, employment, and more.
Installation
pip install bcbpy
Or from source:
git clone https://github.com/rteoo/bcbpy.git
cd bcbpy
pip install .
Requirements
- Python 3.10+
- pandas
- requests
Quick Start
from bcbpy import fetch_series, fetch_last, fetch_multiple, INTEREST_RATES, EXCHANGE_RATES
# Last 10 CDI daily rates
cdi = fetch_last(INTEREST_RATES["CDI_DAILY"], n=10)
print(cdi)
# USD/BRL exchange rate for 2024
usd = fetch_series(EXCHANGE_RATES["USD_SALE_DAILY"], start_date="2024-01-01", end_date="2024-12-31")
print(usd)
# Multiple series merged into one DataFrame
df = fetch_multiple(
{"CDI": INTEREST_RATES["CDI_DAILY"], "SELIC": INTEREST_RATES["SELIC_DAILY"]},
start_date="2024-01-01",
end_date="2024-12-31",
)
print(df.tail())
API Reference
Functions
fetch_series(code, start_date=None, end_date=None)
Fetch a time series by its SGS numeric code. Returns a pandas DataFrame indexed by date.
from bcbpy import fetch_series
# Accepts YYYY-MM-DD or DD/MM/YYYY date formats
ipca = fetch_series(433, start_date="2023-01-01", end_date="2024-12-31")
Daily series (CDI, Selic, USD/BRL, …) require a start_date: BCB rejects undated daily queries with HTTP 406, which surfaces as SGSHTTPError carrying BCB's explanation.
fetch_last(code, n=10)
Fetch the last N observations of a series.
from bcbpy import fetch_last
selic = fetch_last(11, n=5)
fetch_multiple(codes_dict, start_date=None, end_date=None)
Fetch multiple series and merge them into a single DataFrame, one column per series.
from bcbpy import fetch_multiple
df = fetch_multiple({"CDI": 12, "SELIC": 11, "TR": 226}, start_date="2024-01-01")
fetch_raw(code, start_date=None, end_date=None, transport=None)
Fetch one SGS window as a RawResult (payload bytes plus request metadata). Same 10-year single-call limit as fetch_series. Does not parse the body.
from bcbpy import fetch_raw
raw = fetch_raw(12, start_date="2024-01-01", end_date="2024-01-31")
print(raw.sha256, raw.source_url, raw.params)
fetch_raw_range(code, start_date=None, end_date=None, transport=None)
Like fetch_raw, but splits ranges longer than 10 years into bounded partitions. Adjacent partitions do not share a calendar day.
from bcbpy import fetch_raw_range
parts = fetch_raw_range(433, start_date="2010-01-01", end_date="2024-12-31")
list_codes(category=None)
Print all available series codes. Pass a category name to filter.
from bcbpy import list_codes
list_codes() # all 114 codes across 14 categories
list_codes("INTEREST_RATES") # only interest rate codes
search_codes(keyword)
Search codes by keyword (case-insensitive). Returns a dict of matches.
from bcbpy import search_codes
results = search_codes("IPCA") # finds 15 IPCA-related codes
results = search_codes("USD") # finds USD exchange rate codes
Exceptions
| Exception | When |
|---|---|
SGSError |
Base class for every error raised by bcbpy, including malformed or non-JSON responses (e.g. an unknown series code) |
SGSHTTPError |
Any other HTTP error status, with BCB's error text in the message. Also a requests.HTTPError. |
SGSRateLimitError |
API returns HTTP 429 (too many requests). retry_after is set from Retry-After when present. |
SGSEmptyResponseError |
No data returned for the given query |
Network failures (timeouts, connection errors) are raised by requests unchanged.
Error Handling
from bcbpy import fetch_series, SGSRateLimitError, SGSEmptyResponseError
try:
df = fetch_series(433, start_date="2024-01-01")
except SGSRateLimitError:
print("Rate limited — wait and retry")
except SGSEmptyResponseError:
print("No data for this date range")
Available Series Codes
114 curated codes organized in 14 categories:
| Category | Series | Examples |
|---|---|---|
EXCHANGE_RATES |
6 | USD/BRL daily sale/purchase, monthly averages |
INTEREST_RATES |
10 | Selic, CDI, TR, TBF, TJLP |
INFLATION |
17 | IPCA, INPC, IGP-M, IGP-DI, IPC-Fipe |
IPCA_BREAKDOWN |
11 | Tradeable, non-tradeable, durables, services, cores |
IPCA_CATEGORIES |
9 | Food, housing, transport, health, education |
GDP |
13 | GDP current/constant/USD, per capita, quarterly components |
EMPLOYMENT |
7 | Unemployment rate, labor force, income |
INDUSTRIAL_PRODUCTION |
6 | Manufacturing, mining, capital/intermediate/consumer goods |
FINANCIAL_MARKETS |
7 | Gold, Bovespa, IMA-B |
SAVINGS |
2 | Savings rate and return |
CONFIDENCE |
4 | Consumer (ICC) and business (ICEI) confidence |
ECONOMIC_ACTIVITY |
1 | IBC-Br (GDP proxy, seasonally adjusted) |
BASIC_BASKET |
16 | Cost of living by capital city |
EXCHANGE_RATE_INDEX |
5 | Real effective exchange rate (USD, EUR, JPY, ARS) |
Use any code directly by number or via the category dictionaries:
from bcbpy import INFLATION, GDP
# These are equivalent:
fetch_series(433)
fetch_series(INFLATION["IPCA"])
Discontinued series
These registered series have stopped updating in SGS (last observation as of September 2026). Historical data is still available; recent windows return SGSEmptyResponseError.
| Series | Last observation |
|---|---|
FINANCIAL_MARKETS: GOLD_BMF_GRAM, GOLD_LONDON_OZ, BOVESPA_INDEX, BOVESPA_VOLUME |
Sep 2019 |
EMPLOYMENT["FORMAL_EMPLOYMENT_TOTAL"] |
Dec 2019 |
INFLATION["ICV_DIEESE"] |
Feb 2020 |
FINANCIAL_MARKETS: IMA_B, IMA_B5, IMA_B5_PLUS |
May 2023 |
BASIC_BASKET (all cities) |
Jun 2025 |
INFLATION: IGP_M_1ST_DECENNIAL, IGP_M_2ND_DECENNIAL, IPC_FIPE_1ST_QUAD, IPC_FIPE_2ND_QUAD, IPC_FIPE_3RD_QUAD |
Jul 2025 |
API Limits
- Date range: max 10 years per single query (BCB restriction since March 2025).
fetch_series/fetch_rawstill enforce that limit.fetch_raw_rangesplits longer windows into bounded requests. - Rate limiting: HTTP 429 on excessive requests (no official limit documented).
SGSRateLimitError.retry_aftercarriesRetry-Afterwhen the API sends it; the client does not auto-retry. - Daily series: a
start_dateis mandatory; undated queries return HTTP 406. - Unknown series codes: SGS answers with an HTML page (HTTP 200) after about 30 seconds instead of a 404. With the client's 30-second timeout this usually surfaces as
requests.ReadTimeout; when the page arrives in time it raisesSGSError. - Date formats: the client accepts both
YYYY-MM-DDandDD/MM/YYYY
Project Structure
bcbpy/
├── bcbpy/
│ ├── __init__.py # Public API exports
│ ├── artifacts.py # RawResult descriptor
│ ├── client.py # API client functions and exceptions
│ ├── codes.py # 114 curated series codes in 14 categories
│ └── constants.py # Base URLs and API configuration
├── pyproject.toml # PyPI packaging metadata
├── BCB_API_REFERENCE.md # SGS API reference and series code table
└── README.md
Data Source
All data is fetched from the BCB Open Data Portal under the Open Database License (ODbL).
License
MIT (see LICENSE). The BCB data accessed through this client remains under ODbL; users must comply with ODbL when redistributing data.
Release files for bcbpy 2.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bcbpy-2.2.0.tar.gz | 25.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bcbpy-2.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 40.1 kB
Release files / bcbpy-2.2.0.tar.gz
| Download URL | bcbpy-2.2.0.tar.gz |
|---|---|
| Size | 25.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
29cda4d0c59826588428e7ffbd7ce85388485d481fe1bd08c0e4c3ee76d362c5
|
|
BLAKE2b-256 checksum How to use checksums |
1b8fbb6b384872b3a974ff885a8ac9160641c47717964fee5bdde9530dc4b994
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency logRelease files / bcbpy-2.2.0-py3-none-any.whl
| Download URL | bcbpy-2.2.0-py3-none-any.whl |
|---|---|
| Size | 14.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a321f41e9f5d11fb12cf8642294a097a76764d078f54eff7fdbf35a89d0aba5
|
|
BLAKE2b-256 checksum How to use checksums |
fae6118c6f7d6670f0cccd04696c2979864f6273a09d7ddfbd93170f8cefe1ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency log