Context manager

Using Client as a context manager to release its underlying HTTP connection pool deterministically, plus when manual close() is the better fit.

Why

Client opens an httpx.Client under the hood — a connection pool held open for the lifetime of the Client. Using with guarantees that pool is closed as soon as you're done, even if an exception is raised partway through:

with Client(api_key="Aes_...") as client:
    df = client.load_dataset("kenya-housing-prices").to_pandas()

Loading multiple datasets in one session

The client — and its connection pool — is reused across every call inside the block, so prefer one with block over creating a new Client per dataset:

with Client(api_key="Aes_...") as client:
    housing = client.load_dataset("kenya-housing-prices").to_pandas()
    inflation = client.load_dataset("cbk-inflation").to_pandas()

Manual cleanup

If a with block doesn't fit your code's structure (e.g. the client outlives a single function), call .close() yourself once you're done with it:

client = Client(api_key="Aes_...")
try:
    df = client.load_dataset("kenya-housing-prices").to_pandas()
finally:
    client.close()

Scope data loading to the with block

A Dataset returned by load_dataset() keeps a reference back to the Client that created it — it uses that connection to fetch/refresh the dataset's signed Parquet URL. Call .to_pandas(), .to_polars(), .to_duckdb(), .sql(), or .to_csv() on it only while the Client is still open; calling them after the with block has exited (or after .close()) will fail, since the underlying connection pool is gone:

with Client(api_key="Aes_...") as client:
    ds = client.load_dataset("kenya-housing-prices")

df = ds.to_pandas()  # ✗ fails — client is already closed

On this page