Financial Literature

US Bureau of Labor Statistics

BLS API — CPI, jobs and wages straight from the agency that measures them — before FRED mirrors them

Release morning, when you want the official CPI, payrolls or unemployment number the moment it is out, and for the detailed CPI components (shelter, food, energy) that FRED carries only partly.

priceslabourmacroUnited States
Asset classesprices · labour · macro
Frequencymonthly → annual
History1913 → today
Limit · costNo key: 25 queries/day, 10 years per query · free key: 500/day, 20 years
KeyNo key — Optional free registration key (data.bls.gov/registrationEngine) lifts the daily quota and allows 50 series per request.
Formats · pull withjson · csv — python, excel
LicenceUS government work, public domain. Cite BLS and the series id.
RedistributeYes, with attribution
Best for“What did US CPI do last month, from the agency?” · “Payrolls and the unemployment rate on release morning”
When to use it

Reach for it when…

Release morning, when you want the official CPI, payrolls or unemployment number the moment it is out, and for the detailed CPI components (shelter, food, energy) that FRED carries only partly.

Not for: Long-history charting across many series (FRED is quicker), international comparisons (OECD, BIS), anything outside prices and labour.

How to read it

Units, revisions, traps

Units. CPI series are indexes (1982–84 = 100); the headline 'inflation' is the 12-month percent change of the not-seasonally-adjusted index. Payrolls are levels in thousands.

Revisions. Payrolls are revised in each of the next two releases and again at the annual benchmark; CPI is not revised except seasonal factors.

  • CUUR = not seasonally adjusted, CUSR = seasonally adjusted: the 12-month change uses NSA, the month-on-month uses SA.
  • The no-key quota is per IP address and resets daily — a loop can burn it in a minute.
  • Series ids encode the survey: CU (CPI), LN (household survey), CE (payrolls).

Classic mistake: Quoting the month-on-month change of the NSA index in December and calling it a slowdown.

How to use it in your own work

Three recipes

Each recipe: Python · Excel · Sheets, with how to read the result. Python recipes run under pandas; recipe 1 is re-run by the weekly check where the source allows it.

How to use it in your own work

Copy the snippet, change the series id, read the result the way the footer says. Replace YOUR_…_KEY with your own key where one is needed.

Recipe 1CPI-U, 12-month change, no key

# headline CPI-U (NSA index) → 12-month % change
import requests, pandas as pd
u = "https://api.bls.gov/publicAPI/v2/timeseries/data/CUUR0000SA0?startyear=2023&endyear=2026"
rows = requests.get(u, timeout=30).json()["Results"]["series"][0]["data"]
df = pd.DataFrame(rows)
df = df[df.period.str.startswith("M")]
df["date"] = pd.to_datetime(df.year + "-" + df.period.str[1:] + "-01")
s = pd.to_numeric(df.set_index("date")["value"], errors="coerce").sort_index()
print((s.pct_change(12) * 100).dropna().tail(6).round(1))
How to read the resultThe 12-month change is the number the news quotes. Anything under about 2% a year is what the Fed calls its target; the direction over three months matters more than one print.

Recipe 2Payrolls and unemployment in one call

# two series in one POST (no key: up to 25 series per request, 10 years)
import requests, pandas as pd
body = {"seriesid": ["CES0000000001", "LNS14000000"], "startyear": "2022", "endyear": "2026"}
r = requests.post("https://api.bls.gov/publicAPI/v2/timeseries/data/", json=body, timeout=30).json()
out = {}
for s in r["Results"]["series"]:
    d = pd.DataFrame(s["data"]); d = d[d.period.str.startswith("M")]
    d["date"] = pd.to_datetime(d.year + "-" + d.period.str[1:] + "-01")
    out[s["seriesID"]] = d.set_index("date")["value"].astype(float).sort_index()
df = pd.DataFrame(out); df["payroll_change_k"] = df["CES0000000001"].diff()
print(df.tail(6))
How to read the resultPayrolls are a level; the news reports the monthly change (diff). Unemployment comes from a different survey (households) — the two can disagree for months.

Recipe 3Excel: the Data Finder without code

# the same numbers from the CSV the Data Finder exports (download first)
import pandas as pd
df = pd.read_csv("SeriesReport.csv", skiprows=11)   # header rows vary by export
print(df.head())
How to read the resultThe export shows one column per year and one row per month — pivot it back to a single date column before charting.

Series → question map

The ids we use from BLS API, each with the question it answers. The catalog's compare view reads the concept tags behind these rows.

SeriesAnswersRegionConcept
CUUR0000SA0What is US inflation doing? (CPI-U, NSA index)United Statescpi
CUSR0000SA0Month-on-month CPI (seasonally adjusted)United Statescpi
LNS14000000What is the unemployment rate?United Statesunemployment
CES0000000001How many jobs were added? (nonfarm payrolls, thousands)United Statespayrolls
CES0500000003Are wages rising? (average hourly earnings, private)United Stateswages
CUUR0000SAH1Is shelter inflation cooling?United Statescpi

Compare with

Same question, different source: FRED, BEA API, Eurostat API. The compare view lines up coverage, frequency, history and access side by side and lists what the combination makes possible.

Open compare: BLS API · FRED · BEA API →

Curated: Recession watch: the curve and the claims.

Questions readers ask

Do I need a BLS API key?

No for up to 25 requests a day and 10 years per series. A free registration key raises that to 500 a day, 20 years and 50 series per request.

Why does the BLS CPI differ from FRED's CPIAUCSL?

Same survey, different adjustment: CUUR0000SA0 is not seasonally adjusted, CPIAUCSL is. Their 12-month changes agree closely; month-on-month values differ.

When is CPI released?

Usually mid-month at 08:30 Eastern for the previous month; the schedule is at bls.gov/schedule/news_release/cpi.htm.

From the paper

Educational only — we explain, we never advise · snippet licence: public domain · corrections to [email protected], fixed within a day and logged in the changelog.