Skip to content

API reference

Auto-generated from the package docstrings.

Query functions

comex_query

comex_query(flow: str = 'export', start_period: str = None, end_period: str = None, details: Details = None, filters: Filters = None, month_detail: bool = True, metric_fob: bool = True, metric_kg: bool = True, metric_statistic: bool = False, metric_freight: bool = False, metric_insurance: bool = False, metric_cif: bool = False, language: str = 'en', verbose: bool = True) -> pd.DataFrame

Query general Brazilian foreign trade data (1997-present).

Supports filtering and grouping by multiple classifications such as NCM, Harmonized System, countries, states, etc. Data is available monthly from 1997 to the most recent complete month.

Parameters:

Name Type Description Default
flow str

Trade flow: "export" or "import".

'export'
start_period str

Period bounds in "YYYY-MM" format (e.g. "2023-01").

None
end_period str

Period bounds in "YYYY-MM" format (e.g. "2023-01").

None
details str or sequence of str

Detail/grouping fields. The names below are user-friendly aliases; the package translates each to the underlying API name. The API names returned by comex_details("general") are also accepted verbatim.

  • Geographic: "country", "bloc" ("economic_block"), "state", "transport_mode" (API via), "customs_unit" (API urf)
  • Products: "ncm", "hs6"/"sh6" (API subHeading), "hs4"/"sh4" (API heading), "hs2"/"sh2" (API chapter), "section"
  • CGCE (BEC): "cgce_n1", "cgce_n2", "cgce_n3"
  • SITC/CUCI: "sitc_section", "sitc_division", "sitc_group", "sitc_subgroup", "sitc_basic_heading"
  • ISIC: "isic_section", "isic_division", "isic_group", "isic_class"
None
filters mapping

Mapping of filter name to value(s). Names match the detail fields. Example: {"country": [160, 249], "state": [26, 13]}.

None
month_detail bool

If True (default), break down results by month.

True
metric_fob bool

Metrics to include. FOB (US$) and net weight (kg) default to True; freight, insurance and CIF apply to imports only.

True
metric_kg bool

Metrics to include. FOB (US$) and net weight (kg) default to True; freight, insurance and CIF apply to imports only.

True
metric_statistic bool

Metrics to include. FOB (US$) and net weight (kg) default to True; freight, insurance and CIF apply to imports only.

True
metric_freight bool

Metrics to include. FOB (US$) and net weight (kg) default to True; freight, insurance and CIF apply to imports only.

True
metric_insurance bool

Metrics to include. FOB (US$) and net weight (kg) default to True; freight, insurance and CIF apply to imports only.

True
metric_cif bool

Metrics to include. FOB (US$) and net weight (kg) default to True; freight, insurance and CIF apply to imports only.

True
language str

Response language: "pt", "en" or "es" (default "en").

'en'
verbose bool

Show progress messages (default True).

True

Returns:

Type Description
DataFrame

The query results.

Examples:

>>> comex_query(flow="export", start_period="2023-01",
...             end_period="2023-12", details="country")
Source code in src/comexpy/query.py
def comex_query(
    flow: str = "export",
    start_period: str = None,
    end_period: str = None,
    details: Details = None,
    filters: Filters = None,
    month_detail: bool = True,
    metric_fob: bool = True,
    metric_kg: bool = True,
    metric_statistic: bool = False,
    metric_freight: bool = False,
    metric_insurance: bool = False,
    metric_cif: bool = False,
    language: str = "en",
    verbose: bool = True,
) -> pd.DataFrame:
    """Query general Brazilian foreign trade data (1997-present).

    Supports filtering and grouping by multiple classifications such as NCM,
    Harmonized System, countries, states, etc. Data is available monthly from
    1997 to the most recent complete month.

    Parameters
    ----------
    flow : str
        Trade flow: ``"export"`` or ``"import"``.
    start_period, end_period : str
        Period bounds in ``"YYYY-MM"`` format (e.g. ``"2023-01"``).
    details : str or sequence of str, optional
        Detail/grouping fields. The names below are user-friendly aliases;
        the package translates each to the underlying API name. The API names
        returned by ``comex_details("general")`` are also accepted verbatim.

        * **Geographic:** ``"country"``, ``"bloc"`` (``"economic_block"``),
          ``"state"``, ``"transport_mode"`` (API ``via``),
          ``"customs_unit"`` (API ``urf``)
        * **Products:** ``"ncm"``, ``"hs6"``/``"sh6"`` (API ``subHeading``),
          ``"hs4"``/``"sh4"`` (API ``heading``), ``"hs2"``/``"sh2"``
          (API ``chapter``), ``"section"``
        * **CGCE (BEC):** ``"cgce_n1"``, ``"cgce_n2"``, ``"cgce_n3"``
        * **SITC/CUCI:** ``"sitc_section"``, ``"sitc_division"``,
          ``"sitc_group"``, ``"sitc_subgroup"``, ``"sitc_basic_heading"``
        * **ISIC:** ``"isic_section"``, ``"isic_division"``,
          ``"isic_group"``, ``"isic_class"``
    filters : mapping, optional
        Mapping of filter name to value(s). Names match the detail fields.
        Example: ``{"country": [160, 249], "state": [26, 13]}``.
    month_detail : bool
        If ``True`` (default), break down results by month.
    metric_fob, metric_kg, metric_statistic, metric_freight, \
metric_insurance, metric_cif : bool
        Metrics to include. FOB (US$) and net weight (kg) default to ``True``;
        freight, insurance and CIF apply to imports only.
    language : str
        Response language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    verbose : bool
        Show progress messages (default ``True``).

    Returns
    -------
    pandas.DataFrame
        The query results.

    Examples
    --------
    >>> comex_query(flow="export", start_period="2023-01",
    ...             end_period="2023-12", details="country")  # doctest: +SKIP
    """
    validate_period(start_period, end_period)
    flow_api = convert_flow(flow)

    if verbose:
        label = "exports" if flow_api == "export" else "imports"
        _msg.info(f"Querying {label} from {start_period} to {end_period}")

    body = {
        "flow": flow_api,
        "monthDetail": month_detail,
        "period": {"from": start_period, "to": end_period},
        "filters": build_filters(filters),
        "details": build_details(details),
        "metrics": build_metrics(
            metric_fob=metric_fob,
            metric_kg=metric_kg,
            metric_statistic=metric_statistic,
            metric_freight=metric_freight,
            metric_insurance=metric_insurance,
            metric_cif=metric_cif,
        ),
    }

    data = comex_post("/general", body, query={"language": language}, verbose=verbose)
    result = response_to_df(data)

    if verbose and len(result) > 0:
        _msg.success(f"{len(result)} records found")

    return result

comex_export

comex_export(start_period: str, end_period: str, details: Details = None, filters: Filters = None, month_detail: bool = True, metric_fob: bool = True, metric_kg: bool = True, metric_statistic: bool = False, metric_freight: bool = False, metric_insurance: bool = False, metric_cif: bool = False, language: str = 'en', verbose: bool = True) -> pd.DataFrame

Query exports — shortcut for :func:comex_query with flow="export".

Source code in src/comexpy/query.py
def comex_export(
    start_period: str,
    end_period: str,
    details: Details = None,
    filters: Filters = None,
    month_detail: bool = True,
    metric_fob: bool = True,
    metric_kg: bool = True,
    metric_statistic: bool = False,
    metric_freight: bool = False,
    metric_insurance: bool = False,
    metric_cif: bool = False,
    language: str = "en",
    verbose: bool = True,
) -> pd.DataFrame:
    """Query exports — shortcut for :func:`comex_query` with ``flow="export"``."""
    return comex_query(
        flow="export",
        start_period=start_period,
        end_period=end_period,
        details=details,
        filters=filters,
        month_detail=month_detail,
        metric_fob=metric_fob,
        metric_kg=metric_kg,
        metric_statistic=metric_statistic,
        metric_freight=metric_freight,
        metric_insurance=metric_insurance,
        metric_cif=metric_cif,
        language=language,
        verbose=verbose,
    )

comex_import

comex_import(start_period: str, end_period: str, details: Details = None, filters: Filters = None, month_detail: bool = True, metric_fob: bool = True, metric_kg: bool = True, metric_statistic: bool = False, metric_freight: bool = False, metric_insurance: bool = False, metric_cif: bool = False, language: str = 'en', verbose: bool = True) -> pd.DataFrame

Query imports — shortcut for :func:comex_query with flow="import".

Source code in src/comexpy/query.py
def comex_import(
    start_period: str,
    end_period: str,
    details: Details = None,
    filters: Filters = None,
    month_detail: bool = True,
    metric_fob: bool = True,
    metric_kg: bool = True,
    metric_statistic: bool = False,
    metric_freight: bool = False,
    metric_insurance: bool = False,
    metric_cif: bool = False,
    language: str = "en",
    verbose: bool = True,
) -> pd.DataFrame:
    """Query imports — shortcut for :func:`comex_query` with ``flow="import"``."""
    return comex_query(
        flow="import",
        start_period=start_period,
        end_period=end_period,
        details=details,
        filters=filters,
        month_detail=month_detail,
        metric_fob=metric_fob,
        metric_kg=metric_kg,
        metric_statistic=metric_statistic,
        metric_freight=metric_freight,
        metric_insurance=metric_insurance,
        metric_cif=metric_cif,
        language=language,
        verbose=verbose,
    )

comex_query_city

comex_query_city(flow: str = 'export', start_period: str = None, end_period: str = None, details: Details = None, filters: Filters = None, month_detail: bool = True, metric_fob: bool = True, metric_kg: bool = True, language: str = 'en', verbose: bool = True) -> pd.DataFrame

Query city-level Brazilian foreign trade data.

City-level data is more aggregated than general data, with fewer available details and metrics. City information is based on the declarant of exports/imports, not the producer or buyer.

Parameters:

Name Type Description Default
flow str

Trade flow: "export" or "import".

'export'
start_period str

Period bounds in "YYYY-MM" format.

None
end_period str

Period bounds in "YYYY-MM" format.

None
details str or sequence of str

Detail/grouping fields. The city endpoint accepts only a subset of the general fields:

  • Geographic: "country", "bloc" ("economic_block"), "state", "city"
  • Products: "hs4"/"sh4" (API heading), "hs2"/"sh2" (API chapter), "section"
None
filters mapping

Mapping of filter name to value(s). Accepts the same names as details. Example: {"city": "3550308", "state": "26"}.

None
month_detail bool

If True (default), break down results by month.

True
metric_fob bool

Only FOB (US$) and net weight (kg) are supported at city level.

True
metric_kg bool

Only FOB (US$) and net weight (kg) are supported at city level.

True
language str

Response language: "pt", "en" or "es" (default "en").

'en'
verbose bool

Show progress messages (default True).

True

Returns:

Type Description
DataFrame

The query results.

Notes

City-level data differs from general data: full NCM and HS6 are not available (product detail goes only to HS4); CGCE, SITC and ISIC are not available; transport mode and customs unit are not available; and only FOB and KG metrics are supported.

Source code in src/comexpy/query_city.py
def comex_query_city(
    flow: str = "export",
    start_period: str = None,
    end_period: str = None,
    details: Details = None,
    filters: Filters = None,
    month_detail: bool = True,
    metric_fob: bool = True,
    metric_kg: bool = True,
    language: str = "en",
    verbose: bool = True,
) -> pd.DataFrame:
    """Query city-level Brazilian foreign trade data.

    City-level data is more aggregated than general data, with fewer
    available details and metrics. City information is based on the declarant
    of exports/imports, not the producer or buyer.

    Parameters
    ----------
    flow : str
        Trade flow: ``"export"`` or ``"import"``.
    start_period, end_period : str
        Period bounds in ``"YYYY-MM"`` format.
    details : str or sequence of str, optional
        Detail/grouping fields. The city endpoint accepts only a subset of
        the general fields:

        * **Geographic:** ``"country"``, ``"bloc"`` (``"economic_block"``),
          ``"state"``, ``"city"``
        * **Products:** ``"hs4"``/``"sh4"`` (API ``heading``),
          ``"hs2"``/``"sh2"`` (API ``chapter``), ``"section"``
    filters : mapping, optional
        Mapping of filter name to value(s). Accepts the same names as
        ``details``. Example: ``{"city": "3550308", "state": "26"}``.
    month_detail : bool
        If ``True`` (default), break down results by month.
    metric_fob, metric_kg : bool
        Only FOB (US$) and net weight (kg) are supported at city level.
    language : str
        Response language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    verbose : bool
        Show progress messages (default ``True``).

    Returns
    -------
    pandas.DataFrame
        The query results.

    Notes
    -----
    City-level data differs from general data: full NCM and HS6 are not
    available (product detail goes only to HS4); CGCE, SITC and ISIC are not
    available; transport mode and customs unit are not available; and only
    FOB and KG metrics are supported.
    """
    validate_period(start_period, end_period)
    flow_api = convert_flow(flow)

    if verbose:
        label = "exports" if flow_api == "export" else "imports"
        _msg.info(
            f"Querying city-level {label} from {start_period} to {end_period}"
        )

    metrics = []
    if metric_fob:
        metrics.append("metricFOB")
    if metric_kg:
        metrics.append("metricKG")
    if not metrics:
        raise ValueError(
            "At least one metric must be selected (metric_fob or metric_kg)."
        )

    body = {
        "flow": flow_api,
        "monthDetail": month_detail,
        "period": {"from": start_period, "to": end_period},
        "filters": build_filters(filters),
        "details": build_details(details),
        "metrics": metrics,
    }

    data = comex_post("/cities", body, query={"language": language}, verbose=verbose)
    result = response_to_df(data)

    if verbose and len(result) > 0:
        _msg.success(f"{len(result)} records found")

    return result

comex_historical

comex_historical(flow: str = 'export', start_period: str = None, end_period: str = None, details: Details = None, filters: Filters = None, month_detail: bool = True, metric_fob: bool = True, metric_kg: bool = True, language: str = 'en', verbose: bool = True) -> pd.DataFrame

Query historical Brazilian foreign trade data (1989-1996).

Retrieves export and import data from before the SISCOMEX system was implemented. Historical data uses the NBM (Brazilian Nomenclature of Goods) classification.

Parameters:

Name Type Description Default
flow str

Trade flow: "export" or "import".

'export'
start_period str

Period bounds in "YYYY-MM" format (e.g. "1990-01").

None
end_period str

Period bounds in "YYYY-MM" format (e.g. "1990-01").

None
details str or sequence of str

Detail/grouping fields. The historical endpoint supports only: "country", "bloc" ("economic_block"), "state", "nbm".

None
filters mapping

Mapping of filter name to value(s). Accepts the same names as details.

None
month_detail bool

If True (default), break down results by month.

True
metric_fob bool

Only FOB (US$) and net weight (kg) are supported.

True
metric_kg bool

Only FOB (US$) and net weight (kg) are supported.

True
language str

Response language: "pt", "en" or "es" (default "en").

'en'
verbose bool

Show progress messages (default True).

True

Returns:

Type Description
DataFrame

The query results.

Notes

Historical data is available for 1989 to 1996 only, with limited details ("country", "state", "nbm"), NBM (not NCM) product classification, and only FOB and KG metrics.

Source code in src/comexpy/historical.py
def comex_historical(
    flow: str = "export",
    start_period: str = None,
    end_period: str = None,
    details: Details = None,
    filters: Filters = None,
    month_detail: bool = True,
    metric_fob: bool = True,
    metric_kg: bool = True,
    language: str = "en",
    verbose: bool = True,
) -> pd.DataFrame:
    """Query historical Brazilian foreign trade data (1989-1996).

    Retrieves export and import data from before the SISCOMEX system was
    implemented. Historical data uses the NBM (Brazilian Nomenclature of
    Goods) classification.

    Parameters
    ----------
    flow : str
        Trade flow: ``"export"`` or ``"import"``.
    start_period, end_period : str
        Period bounds in ``"YYYY-MM"`` format (e.g. ``"1990-01"``).
    details : str or sequence of str, optional
        Detail/grouping fields. The historical endpoint supports only:
        ``"country"``, ``"bloc"`` (``"economic_block"``), ``"state"``,
        ``"nbm"``.
    filters : mapping, optional
        Mapping of filter name to value(s). Accepts the same names as
        ``details``.
    month_detail : bool
        If ``True`` (default), break down results by month.
    metric_fob, metric_kg : bool
        Only FOB (US$) and net weight (kg) are supported.
    language : str
        Response language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    verbose : bool
        Show progress messages (default ``True``).

    Returns
    -------
    pandas.DataFrame
        The query results.

    Notes
    -----
    Historical data is available for **1989 to 1996** only, with limited
    details (``"country"``, ``"state"``, ``"nbm"``), NBM (not NCM) product
    classification, and only FOB and KG metrics.
    """
    validate_period(start_period, end_period)
    flow_api = convert_flow(flow)

    start_year = int(str(start_period)[:4])
    end_year = int(str(end_period)[:4])
    if start_year < 1989 or end_year > 1996:
        _msg.warn(
            "Historical data is available from 1989 to 1996. "
            f"Requested period: {start_period} to {end_period}"
        )

    if verbose:
        label = "exports" if flow_api == "export" else "imports"
        _msg.info(
            f"Querying historical {label} from {start_period} to {end_period}"
        )

    metrics = []
    if metric_fob:
        metrics.append("metricFOB")
    if metric_kg:
        metrics.append("metricKG")
    if not metrics:
        raise ValueError(
            "At least one metric must be selected (metric_fob or metric_kg)."
        )

    body = {
        "flow": flow_api,
        "monthDetail": month_detail,
        "period": {"from": start_period, "to": end_period},
        "filters": build_filters(filters),
        "details": build_details(details),
        "metrics": metrics,
    }

    # The API spec defines this endpoint with a trailing slash.
    data = comex_post(
        "/historical-data/", body, query={"language": language}, verbose=verbose
    )
    result = response_to_df(data)

    if verbose and len(result) > 0:
        _msg.success(f"{len(result)} records found")

    return result

API metadata

comex_last_update

comex_last_update(type: str = 'general', verbose: bool = False) -> Any

Date of the last data update in the API.

Parameters:

Name Type Description Default
type str

Data type: "general", "city" or "historical".

'general'
verbose bool

Show progress messages (default False).

False

Returns:

Type Description
dict

Last-update information.

Source code in src/comexpy/tables.py
def comex_last_update(type: str = "general", verbose: bool = False) -> Any:
    """Date of the last data update in the API.

    Parameters
    ----------
    type : str
        Data type: ``"general"``, ``"city"`` or ``"historical"``.
    verbose : bool
        Show progress messages (default ``False``).

    Returns
    -------
    dict
        Last-update information.
    """
    endpoint = _base_for(type) + "/dates/updated"
    return extract_single(comex_get(endpoint, verbose=verbose))

comex_available_years

comex_available_years(type: str = 'general', verbose: bool = False) -> Any

First and last years available for queries.

Parameters:

Name Type Description Default
type str

Data type: "general", "city" or "historical".

'general'
verbose bool

Show progress messages (default False).

False

Returns:

Type Description
dict

Mapping with min and max year values.

Source code in src/comexpy/tables.py
def comex_available_years(type: str = "general", verbose: bool = False) -> Any:
    """First and last years available for queries.

    Parameters
    ----------
    type : str
        Data type: ``"general"``, ``"city"`` or ``"historical"``.
    verbose : bool
        Show progress messages (default ``False``).

    Returns
    -------
    dict
        Mapping with ``min`` and ``max`` year values.
    """
    endpoint = _base_for(type) + "/dates/years"
    return extract_single(comex_get(endpoint, verbose=verbose))

comex_filters

comex_filters(type: str = 'general', language: str = 'en', verbose: bool = False) -> pd.DataFrame

List of filter types available for API queries.

Source code in src/comexpy/tables.py
def comex_filters(
    type: str = "general", language: str = "en", verbose: bool = False
) -> pd.DataFrame:
    """List of filter types available for API queries."""
    endpoint = _base_for(type) + "/filters"
    data = comex_get(endpoint, query={"language": language}, verbose=verbose)
    return response_to_df(data)

comex_filter_values

comex_filter_values(filter: str, type: str = 'general', language: str = 'en', verbose: bool = False) -> pd.DataFrame

Possible values for a given filter.

The filter argument is passed verbatim to the API and is case-sensitive — use the exact name returned by :func:comex_filters (e.g. "economicBlock", "BECLevel1", "SITCSection", "ISICSection", "subHeading", "heading", "chapter").

Parameters:

Name Type Description Default
filter str

Filter name as returned by :func:comex_filters.

required
type str

Data type: "general", "city" or "historical".

'general'
language str

Language: "pt", "en" or "es" (default "en").

'en'
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables.py
def comex_filter_values(
    filter: str,
    type: str = "general",
    language: str = "en",
    verbose: bool = False,
) -> pd.DataFrame:
    """Possible values for a given filter.

    The ``filter`` argument is passed verbatim to the API and is
    case-sensitive — use the exact name returned by :func:`comex_filters`
    (e.g. ``"economicBlock"``, ``"BECLevel1"``, ``"SITCSection"``,
    ``"ISICSection"``, ``"subHeading"``, ``"heading"``, ``"chapter"``).

    Parameters
    ----------
    filter : str
        Filter name as returned by :func:`comex_filters`.
    type : str
        Data type: ``"general"``, ``"city"`` or ``"historical"``.
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    verbose : bool
        Show progress messages (default ``False``).
    """
    endpoint = _base_for(type) + "/filters/" + str(filter)
    data = comex_get(endpoint, query={"language": language}, verbose=verbose)
    return response_to_df(data)

comex_details

comex_details(type: str = 'general', language: str = 'en', verbose: bool = False) -> pd.DataFrame

Detail/grouping fields that can be used to group query results.

Source code in src/comexpy/tables.py
def comex_details(
    type: str = "general", language: str = "en", verbose: bool = False
) -> pd.DataFrame:
    """Detail/grouping fields that can be used to group query results."""
    endpoint = _base_for(type) + "/details"
    data = comex_get(endpoint, query={"language": language}, verbose=verbose)
    return response_to_df(data)

comex_metrics

comex_metrics(type: str = 'general', language: str = 'en', verbose: bool = False) -> pd.DataFrame

Metrics (values) available for API queries.

Source code in src/comexpy/tables.py
def comex_metrics(
    type: str = "general", language: str = "en", verbose: bool = False
) -> pd.DataFrame:
    """Metrics (values) available for API queries."""
    endpoint = _base_for(type) + "/metrics"
    data = comex_get(endpoint, query={"language": language}, verbose=verbose)
    return response_to_df(data)

Auxiliary tables — geography

comex_countries

comex_countries(search: Optional[str] = None, verbose: bool = False) -> pd.DataFrame

Countries table with codes and names.

Parameters:

Name Type Description Default
search str

Search term to filter results (e.g. "bra").

None
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables.py
def comex_countries(
    search: Optional[str] = None, verbose: bool = False
) -> pd.DataFrame:
    """Countries table with codes and names.

    Parameters
    ----------
    search : str, optional
        Search term to filter results (e.g. ``"bra"``).
    verbose : bool
        Show progress messages (default ``False``).
    """
    data = comex_get(
        "/tables/countries", query={"search": search}, verbose=verbose
    )
    return response_to_df(data)

comex_country_detail

comex_country_detail(id: Any, verbose: bool = False) -> Any

Details for a specific country by its code (e.g. 105 for Brazil).

Source code in src/comexpy/tables.py
def comex_country_detail(id: Any, verbose: bool = False) -> Any:
    """Details for a specific country by its code (e.g. ``105`` for Brazil)."""
    data = comex_get(f"/tables/countries/{id}", verbose=verbose)
    return extract_single(data)

comex_blocs

comex_blocs(language: str = 'en', search: Optional[str] = None, add: Optional[str] = None, verbose: bool = False) -> pd.DataFrame

Economic blocs table (trade agreements between countries/regions).

Parameters:

Name Type Description Default
language str

Language: "pt", "en" or "es" (default "en").

'en'
search str

Search term to filter results.

None
add str

Related table to include (e.g. "country").

None
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables.py
def comex_blocs(
    language: str = "en",
    search: Optional[str] = None,
    add: Optional[str] = None,
    verbose: bool = False,
) -> pd.DataFrame:
    """Economic blocs table (trade agreements between countries/regions).

    Parameters
    ----------
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    search : str, optional
        Search term to filter results.
    add : str, optional
        Related table to include (e.g. ``"country"``).
    verbose : bool
        Show progress messages (default ``False``).
    """
    data = comex_get(
        "/tables/economic-blocks",
        query={"language": language, "search": search, "add": add},
        verbose=verbose,
    )
    return response_to_df(data)

comex_states

comex_states(verbose: bool = False) -> pd.DataFrame

Brazilian states (UF) table with codes and names.

Source code in src/comexpy/tables.py
def comex_states(verbose: bool = False) -> pd.DataFrame:
    """Brazilian states (UF) table with codes and names."""
    return response_to_df(comex_get("/tables/uf", verbose=verbose))

comex_state_detail

comex_state_detail(uf_id: Any, verbose: bool = False) -> Any

Details for a specific Brazilian state (e.g. 26 for Pernambuco).

Source code in src/comexpy/tables.py
def comex_state_detail(uf_id: Any, verbose: bool = False) -> Any:
    """Details for a specific Brazilian state (e.g. ``26`` for Pernambuco)."""
    data = comex_get(f"/tables/uf/{uf_id}", verbose=verbose)
    return extract_single(data)

comex_cities

comex_cities(verbose: bool = False) -> pd.DataFrame

Brazilian cities table with IBGE codes and names.

Source code in src/comexpy/tables.py
def comex_cities(verbose: bool = False) -> pd.DataFrame:
    """Brazilian cities table with IBGE codes and names."""
    return response_to_df(comex_get("/tables/cities", verbose=verbose))

comex_city_detail

comex_city_detail(city_id: Any, verbose: bool = False) -> Any

Details for a specific Brazilian city (e.g. 5300050).

Source code in src/comexpy/tables.py
def comex_city_detail(city_id: Any, verbose: bool = False) -> Any:
    """Details for a specific Brazilian city (e.g. ``5300050``)."""
    data = comex_get(f"/tables/cities/{city_id}", verbose=verbose)
    return extract_single(data)

comex_transport_modes

comex_transport_modes(verbose: bool = False) -> pd.DataFrame

Transport modes table with codes and names.

Source code in src/comexpy/tables.py
def comex_transport_modes(verbose: bool = False) -> pd.DataFrame:
    """Transport modes table with codes and names."""
    return response_to_df(comex_get("/tables/ways", verbose=verbose))

comex_transport_mode_detail

comex_transport_mode_detail(mode_id: Any, verbose: bool = False) -> Any

Details for a specific transport mode (e.g. 5 for maritime).

Source code in src/comexpy/tables.py
def comex_transport_mode_detail(mode_id: Any, verbose: bool = False) -> Any:
    """Details for a specific transport mode (e.g. ``5`` for maritime)."""
    data = comex_get(f"/tables/ways/{mode_id}", verbose=verbose)
    return extract_single(data)

comex_customs_units

comex_customs_units(verbose: bool = False) -> pd.DataFrame

Customs units (URF) table.

The Federal Revenue Service administrative units (Unidades da Receita Federal) responsible for overseeing foreign trade operations.

Source code in src/comexpy/tables.py
def comex_customs_units(verbose: bool = False) -> pd.DataFrame:
    """Customs units (URF) table.

    The Federal Revenue Service administrative units (Unidades da Receita
    Federal) responsible for overseeing foreign trade operations.
    """
    return response_to_df(comex_get("/tables/urf", verbose=verbose))

comex_customs_unit_detail

comex_customs_unit_detail(urf_id: Any, verbose: bool = False) -> Any

Details for a specific customs unit (URF) (e.g. 8110000).

Source code in src/comexpy/tables.py
def comex_customs_unit_detail(urf_id: Any, verbose: bool = False) -> Any:
    """Details for a specific customs unit (URF) (e.g. ``8110000``)."""
    data = comex_get(f"/tables/urf/{urf_id}", verbose=verbose)
    return extract_single(data)

Auxiliary tables — products

comex_ncm

comex_ncm(language: str = 'en', search: Optional[str] = None, add: Optional[str] = None, page: Optional[int] = None, per_page: Optional[int] = None, verbose: bool = False) -> pd.DataFrame

NCM (Mercosur Common Nomenclature) table with descriptions.

NCM is the 8-digit product classification used by Mercosur countries, based on the Harmonized System (HS).

Parameters:

Name Type Description Default
language str

Language: "pt", "en" or "es" (default "en").

'en'
search str

Search term to filter results (e.g. "animal").

None
add str

Related table to include: "sh", "cuci" or "cgce".

None
page int

Pagination controls (default returns all results).

None
per_page int

Pagination controls (default returns all results).

None
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables_products.py
def comex_ncm(
    language: str = "en",
    search: Optional[str] = None,
    add: Optional[str] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
    verbose: bool = False,
) -> pd.DataFrame:
    """NCM (Mercosur Common Nomenclature) table with descriptions.

    NCM is the 8-digit product classification used by Mercosur countries,
    based on the Harmonized System (HS).

    Parameters
    ----------
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    search : str, optional
        Search term to filter results (e.g. ``"animal"``).
    add : str, optional
        Related table to include: ``"sh"``, ``"cuci"`` or ``"cgce"``.
    page, per_page : int, optional
        Pagination controls (default returns all results).
    verbose : bool
        Show progress messages (default ``False``).
    """
    data = comex_get(
        "/tables/ncm",
        query={
            "language": language,
            "search": search,
            "add": add,
            "page": page,
            "perPage": per_page,
        },
        verbose=verbose,
    )
    return response_to_df(data)

comex_ncm_detail

comex_ncm_detail(ncm_code: Any, verbose: bool = False) -> Any

Details for a specific NCM code (8 digits, e.g. "02042200").

Source code in src/comexpy/tables_products.py
def comex_ncm_detail(ncm_code: Any, verbose: bool = False) -> Any:
    """Details for a specific NCM code (8 digits, e.g. ``"02042200"``)."""
    data = comex_get(f"/tables/ncm/{ncm_code}", verbose=verbose)
    return extract_single(data)

comex_nbm

comex_nbm(language: str = 'en', search: Optional[str] = None, add: Optional[str] = None, page: Optional[int] = None, per_page: Optional[int] = None, verbose: bool = False) -> pd.DataFrame

NBM (Brazilian Nomenclature of Goods) table with descriptions.

NBM was used in Brazil before NCM adoption and applies only to historical data (1989-1996).

Parameters:

Name Type Description Default
language str

Language: "pt", "en" or "es" (default "en").

'en'
search str

Search term to filter results.

None
add str

Related table to include (e.g. "ncm").

None
page int

Pagination controls.

None
per_page int

Pagination controls.

None
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables_products.py
def comex_nbm(
    language: str = "en",
    search: Optional[str] = None,
    add: Optional[str] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
    verbose: bool = False,
) -> pd.DataFrame:
    """NBM (Brazilian Nomenclature of Goods) table with descriptions.

    NBM was used in Brazil before NCM adoption and applies only to historical
    data (1989-1996).

    Parameters
    ----------
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    search : str, optional
        Search term to filter results.
    add : str, optional
        Related table to include (e.g. ``"ncm"``).
    page, per_page : int, optional
        Pagination controls.
    verbose : bool
        Show progress messages (default ``False``).
    """
    data = comex_get(
        "/tables/nbm",
        query={
            "language": language,
            "search": search,
            "add": add,
            "page": page,
            "perPage": per_page,
        },
        verbose=verbose,
    )
    return response_to_df(data)

comex_nbm_detail

comex_nbm_detail(nbm_code: Any, verbose: bool = False) -> Any

Details for a specific NBM code (e.g. "2924101100").

Source code in src/comexpy/tables_products.py
def comex_nbm_detail(nbm_code: Any, verbose: bool = False) -> Any:
    """Details for a specific NBM code (e.g. ``"2924101100"``)."""
    data = comex_get(f"/tables/nbm/{nbm_code}", verbose=verbose)
    return extract_single(data)

comex_hs

comex_hs(language: str = 'en', add: Optional[str] = None, page: Optional[int] = None, per_page: Optional[int] = None, verbose: bool = False) -> pd.DataFrame

Harmonized System (HS) classification tables.

The HS is an international product nomenclature developed by the World Customs Organization, organised hierarchically: Section, Chapter (HS2), Heading (HS4) and Subheading (HS6). NCM adds two more digits to HS6.

Parameters:

Name Type Description Default
language str

Language: "pt", "en" or "es" (default "en").

'en'
add str

Related table to include (e.g. "ncm").

None
page int

Pagination controls.

None
per_page int

Pagination controls.

None
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables_products.py
def comex_hs(
    language: str = "en",
    add: Optional[str] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
    verbose: bool = False,
) -> pd.DataFrame:
    """Harmonized System (HS) classification tables.

    The HS is an international product nomenclature developed by the World
    Customs Organization, organised hierarchically: Section, Chapter (HS2),
    Heading (HS4) and Subheading (HS6). NCM adds two more digits to HS6.

    Parameters
    ----------
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    add : str, optional
        Related table to include (e.g. ``"ncm"``).
    page, per_page : int, optional
        Pagination controls.
    verbose : bool
        Show progress messages (default ``False``).
    """
    data = comex_get(
        "/tables/hs",
        query={
            "language": language,
            "add": add,
            "page": page,
            "perPage": per_page,
        },
        verbose=verbose,
    )
    return response_to_df(data)

Auxiliary tables — classifications

comex_cgce

comex_cgce(language: str = 'en', search: Optional[str] = None, add: Optional[str] = None, page: Optional[int] = None, per_page: Optional[int] = None, verbose: bool = False) -> pd.DataFrame

CGCE (Classification by Broad Economic Categories) table.

CGCE groups products by use or economic purpose (e.g. capital goods, intermediate goods, consumer goods). Served by /tables/classifications.

Parameters:

Name Type Description Default
language str

Language: "pt", "en" or "es" (default "en").

'en'
search str

Search term to filter results.

None
add str

Related table to include (e.g. "ncm").

None
page int

Pagination controls.

None
per_page int

Pagination controls.

None
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables_classifications.py
def comex_cgce(
    language: str = "en",
    search: Optional[str] = None,
    add: Optional[str] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
    verbose: bool = False,
) -> pd.DataFrame:
    """CGCE (Classification by Broad Economic Categories) table.

    CGCE groups products by use or economic purpose (e.g. capital goods,
    intermediate goods, consumer goods). Served by ``/tables/classifications``.

    Parameters
    ----------
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    search : str, optional
        Search term to filter results.
    add : str, optional
        Related table to include (e.g. ``"ncm"``).
    page, per_page : int, optional
        Pagination controls.
    verbose : bool
        Show progress messages (default ``False``).
    """
    data = comex_get(
        "/tables/classifications",
        query={
            "language": language,
            "search": search,
            "add": add,
            "page": page,
            "perPage": per_page,
        },
        verbose=verbose,
    )
    return response_to_df(data)

comex_sitc

comex_sitc(language: str = 'en', search: Optional[str] = None, add: Optional[str] = None, page: Optional[int] = None, per_page: Optional[int] = None, verbose: bool = False) -> pd.DataFrame

SITC/CUCI (Standard International Trade Classification) table.

CUCI is the Portuguese name for SITC. Served by the /tables/product-categories endpoint.

Parameters:

Name Type Description Default
language str

Language: "pt", "en" or "es" (default "en").

'en'
search str

Search term to filter results (e.g. "carne").

None
add str

Related table to include (e.g. "ncm").

None
page int

Pagination controls.

None
per_page int

Pagination controls.

None
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables_classifications.py
def comex_sitc(
    language: str = "en",
    search: Optional[str] = None,
    add: Optional[str] = None,
    page: Optional[int] = None,
    per_page: Optional[int] = None,
    verbose: bool = False,
) -> pd.DataFrame:
    """SITC/CUCI (Standard International Trade Classification) table.

    CUCI is the Portuguese name for SITC. Served by the
    ``/tables/product-categories`` endpoint.

    Parameters
    ----------
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    search : str, optional
        Search term to filter results (e.g. ``"carne"``).
    add : str, optional
        Related table to include (e.g. ``"ncm"``).
    page, per_page : int, optional
        Pagination controls.
    verbose : bool
        Show progress messages (default ``False``).
    """
    data = comex_get(
        "/tables/product-categories",
        query={
            "language": language,
            "search": search,
            "add": add,
            "page": page,
            "perPage": per_page,
        },
        verbose=verbose,
    )
    return response_to_df(data)

comex_isic

comex_isic(level: str = 'section', language: str = 'en', verbose: bool = False) -> pd.DataFrame

ISIC (International Standard Industrial Classification) values.

Retrieves ISIC values at a chosen hierarchical level via the /general/filters/{filter} endpoint, which is the only place the ComexStat API exposes ISIC codes (there is no /tables/isic endpoint).

Parameters:

Name Type Description Default
level str

Hierarchical level: "section", "division", "group" or "class" (default "section").

'section'
language str

Language: "pt", "en" or "es" (default "en").

'en'
verbose bool

Show progress messages (default False).

False
Source code in src/comexpy/tables_classifications.py
def comex_isic(
    level: str = "section", language: str = "en", verbose: bool = False
) -> pd.DataFrame:
    """ISIC (International Standard Industrial Classification) values.

    Retrieves ISIC values at a chosen hierarchical level via the
    ``/general/filters/{filter}`` endpoint, which is the only place the
    ComexStat API exposes ISIC codes (there is no ``/tables/isic`` endpoint).

    Parameters
    ----------
    level : str
        Hierarchical level: ``"section"``, ``"division"``, ``"group"`` or
        ``"class"`` (default ``"section"``).
    language : str
        Language: ``"pt"``, ``"en"`` or ``"es"`` (default ``"en"``).
    verbose : bool
        Show progress messages (default ``False``).
    """
    try:
        filter_name = _ISIC_FILTERS[level]
    except KeyError:
        raise ValueError(
            f"Invalid level: {level}. "
            "Use 'section', 'division', 'group', or 'class'."
        )
    return comex_filter_values(
        filter_name, type="general", language=language, verbose=verbose
    )

Configuration

set_options

set_options(*, timeout_get: Optional[int] = None, timeout_post: Optional[int] = None, max_tries: Optional[int] = None, retry_time: Optional[int] = None, ssl_verify: Optional[bool] = None) -> None

Configure HTTP retry/timeout behaviour (equivalent to the R options).

The ComexStat API frequently returns rate-limit errors (HTTP 429, "Você excedeu o limite de solicitações...") or times out. Adjust these settings to work around such errors without overloading the servers.

Parameters:

Name Type Description Default
timeout_get int

Seconds to wait for a response on GET requests (default 60).

None
timeout_post int

Seconds to wait for a response on POST requests (default 120).

None
max_tries int

Maximum number of attempts for a failing request (default 3). Adjusting retry_time is generally a better way to avoid errors.

None
retry_time int

Seconds to wait between retries after a transient failure (default 10, matching the API's recommended back-off).

None
ssl_verify bool

Whether to verify SSL certificates. Set to False to skip verification when the ICP-Brasil certificate chain is not trusted.

None
Source code in src/comexpy/_client.py
def set_options(
    *,
    timeout_get: Optional[int] = None,
    timeout_post: Optional[int] = None,
    max_tries: Optional[int] = None,
    retry_time: Optional[int] = None,
    ssl_verify: Optional[bool] = None,
) -> None:
    """Configure HTTP retry/timeout behaviour (equivalent to the R options).

    The ComexStat API frequently returns rate-limit errors (HTTP 429,
    *"Você excedeu o limite de solicitações..."*) or times out. Adjust these
    settings to work around such errors without overloading the servers.

    Parameters
    ----------
    timeout_get : int, optional
        Seconds to wait for a response on GET requests (default 60).
    timeout_post : int, optional
        Seconds to wait for a response on POST requests (default 120).
    max_tries : int, optional
        Maximum number of attempts for a failing request (default 3).
        Adjusting ``retry_time`` is generally a better way to avoid errors.
    retry_time : int, optional
        Seconds to wait between retries after a transient failure
        (default 10, matching the API's recommended back-off).
    ssl_verify : bool, optional
        Whether to verify SSL certificates. Set to ``False`` to skip
        verification when the ICP-Brasil certificate chain is not trusted.
    """
    if timeout_get is not None:
        _CONFIG["timeout_get"] = int(timeout_get)
    if timeout_post is not None:
        _CONFIG["timeout_post"] = int(timeout_post)
    if max_tries is not None:
        _CONFIG["max_tries"] = int(max_tries)
    if retry_time is not None:
        _CONFIG["retry_time"] = int(retry_time)
    if ssl_verify is not None:
        _CONFIG["ssl_verify"] = bool(ssl_verify)

get_options

get_options() -> dict

Return a copy of the current HTTP configuration.

Source code in src/comexpy/_client.py
def get_options() -> dict:
    """Return a copy of the current HTTP configuration."""
    return dict(_CONFIG)

set_verbose

set_verbose(verbose: bool) -> None

Enable or disable informational messages (success/step/info).

Warnings are always shown. Errors are raised as exceptions.

Parameters:

Name Type Description Default
verbose bool

If False, suppress progress and success messages.

required
Source code in src/comexpy/_msg.py
def set_verbose(verbose: bool) -> None:
    """Enable or disable informational messages (success/step/info).

    Warnings are always shown. Errors are raised as exceptions.

    Parameters
    ----------
    verbose : bool
        If ``False``, suppress progress and success messages.
    """
    global _VERBOSE
    _VERBOSE = bool(verbose)

ComexError

Bases: RuntimeError

Raised when a ComexStat API request fails.