This vignette reproduces a complete state-level trade extract similar to the one offered by the ComexStat web app, with the following combination requested in the “By Municipality” panel:
City-level data refers to the declarant’s tax residence, not the place where the goods were produced or purchased. The city endpoint only goes down to HS4 (heading) — full NCM and HS6 (subHeading) are not available for this view.
Brazilian state codes follow the IBGE convention (26 =
Pernambuco). If you don’t remember the code, query the table:
state_code <- 26 # Pernambuco
period_from <- "2026-01"
period_to <- "2026-12" # API returns up to the latest update
# These names are user-friendly aliases. The package translates each
# to the underlying API name (see `getting-started` vignette for the
# full mapping table):
# hs4 -> heading
# hs2 -> chapter
detalhes <- c("state", "city", "hs4", "section", "hs2", "country")
filtros <- list(state = state_code)The API serves one flow per request, so we make two calls and combine the results:
exp_pe <- comex_query_city(
flow = "export",
start_period = period_from,
end_period = period_to,
details = detalhes,
filters = filtros,
month_detail = TRUE,
metric_fob = TRUE,
metric_kg = TRUE
)
exp_pe$flow <- "export"
imp_pe <- comex_query_city(
flow = "import",
start_period = period_from,
end_period = period_to,
details = detalhes,
filters = filtros,
month_detail = TRUE,
metric_fob = TRUE,
metric_kg = TRUE
)
imp_pe$flow <- "import"
pe <- rbind(exp_pe, imp_pe)The resulting data frame has one row per month × city × HS4 × country × flow combination:
API responses come back as character. Convert metrics to numeric and
build a proper Date column for time-series analysis:
monthly <- aggregate(metricFOB ~ date + flow, data = pe, FUN = sum)
monthly_wide <- reshape(monthly, idvar = "date", timevar = "flow",
direction = "wide")
names(monthly_wide) <- c("date", "exports", "imports")
monthly_wide$balance <- monthly_wide$exports - monthly_wide$imports
monthly_wide
# Base-R plot
with(monthly_wide, {
plot(date, exports / 1e6, type = "b", pch = 19, col = "steelblue",
ylim = range(c(exports, imports), na.rm = TRUE) / 1e6,
xlab = "Month", ylab = "US$ millions",
main = "Pernambuco: exports vs imports, 2026")
lines(date, imports / 1e6, type = "b", pch = 17, col = "tomato")
legend("topleft", legend = c("Exports", "Imports"),
col = c("steelblue", "tomato"), pch = c(19, 17), bty = "n")
})The package returns the city as noMunMinsgUf
(e.g. “Goiana - PE”):
exports_by_city <- aggregate(metricFOB ~ noMunMinsgUf,
data = subset(pe, flow == "export"),
FUN = sum)
head(exports_by_city[order(-exports_by_city$metricFOB), ], 10)
imports_by_city <- aggregate(metricFOB ~ noMunMinsgUf,
data = subset(pe, flow == "import"),
FUN = sum)
head(imports_by_city[order(-imports_by_city$metricFOB), ], 10)exp_hs4 <- aggregate(
metricFOB ~ headingCode + heading,
data = subset(pe, flow == "export"),
FUN = sum
)
head(exp_hs4[order(-exp_hs4$metricFOB), ], 10)
imp_hs4 <- aggregate(
metricFOB ~ headingCode + heading,
data = subset(pe, flow == "import"),
FUN = sum
)
head(imp_hs4[order(-imp_hs4$metricFOB), ], 10)Because pe already contains the full set of details, any
deeper cut is just a matter of aggregate():
# Top product for each top destination
exp_country_hs4 <- aggregate(
metricFOB ~ country + heading,
data = subset(pe, flow == "export"),
FUN = sum
)
exp_country_hs4 <- exp_country_hs4[
order(exp_country_hs4$country, -exp_country_hs4$metricFOB),
]
do.call(rbind, lapply(
split(exp_country_hs4, exp_country_hs4$country),
function(x) head(x, 1)
))
# Top destination for each Pernambuco municipality
exp_city_country <- aggregate(
metricFOB ~ noMunMinsgUf + country,
data = subset(pe, flow == "export"),
FUN = sum
)
exp_city_country <- exp_city_country[
order(exp_city_country$noMunMinsgUf, -exp_city_country$metricFOB),
]
do.call(rbind, lapply(
split(exp_city_country, exp_city_country$noMunMinsgUf),
function(x) head(x, 1)
))To compare with previous years, just widen the date range and drop
month_detail:
yearly_exp <- comex_query_city(
flow = "export",
start_period = "2019-01",
end_period = "2026-12",
details = "state",
filters = list(state = state_code),
month_detail = FALSE
)
yearly_imp <- comex_query_city(
flow = "import",
start_period = "2019-01",
end_period = "2026-12",
details = "state",
filters = list(state = state_code),
month_detail = FALSE
)
yearly_exp$flow <- "export"; yearly_imp$flow <- "import"
yearly <- rbind(yearly_exp, yearly_imp)
yearly$metricFOB <- as.numeric(yearly$metricFOB)
yearly # one row per year × flowThe same code works for any Brazilian state — change only
state_code and the date range. To get the code
interactively:
For analyses that require finer product detail (NCM, HS6) or other
classifications (CGCE, SITC, ISIC), use [comex_query()] /
[comex_export()] / [comex_import()] on the
general endpoint — but those do not accept a city
filter.