Skip to main content

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_raw still enforce that limit. fetch_raw_range splits longer windows into bounded requests.
  • Rate limiting: HTTP 429 on excessive requests (no official limit documented). SGSRateLimitError.retry_after carries Retry-After when the API sends it; the client does not auto-retry.
  • Daily series: a start_date is 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 raises SGSError.
  • Date formats: the client accepts both YYYY-MM-DD and DD/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)

Source distribution for bcbpy 2.2.0
File Size Uploaded
bcbpy-2.2.0.tar.gz 25.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bcbpy 2.2.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

2.2.0 This release

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page