Technical writing

BLS QCEW: The County-Level Employment and Wages Dataset Behind Every Local Economic Analysis

· AI Analytics
Federal DataBLSEmploymentLabor Markets

The Bureau of Labor Statistics Quarterly Census of Employment and Wages is the closest thing the United States has to a complete quarterly census of its workforce. Every quarter it publishes employment and wage totals for every industry in every county — roughly 10 million establishment-quarter records covering more than 155 million UI-covered workers and over $10 trillion in quarterly wages. No other federal dataset delivers that combination of geographic depth, industry granularity, and wage information on a recurring basis.

What QCEW Is and Where It Comes From

QCEW is derived from Unemployment Insurance tax filings. Every employer subject to state UI law must file a quarterly report with the state workforce agency listing the number of workers on payroll in each of the three months of the quarter and the total wages paid during the quarter. State agencies transmit those records to BLS, which aggregates them, applies NAICS industry codes, and publishes the result — typically with a five-month lag after the reference quarter.

Because the source is a tax record rather than a voluntary survey, coverage is close to universal for the employed population: roughly 97% of all US jobs fall within UI-covered employment. That near-census character is what distinguishes QCEW from household surveys like the Current Population Survey or establishment surveys like the Current Employment Statistics program, both of which sample a fraction of the labor market and extrapolate.

What QCEW Covers — and What It Misses

The 97% figure is the headline, but the 3% exclusion is analytically important. QCEW captures establishments with employees subject to state UI taxes or federal FUTA taxes. It does not capture:

Analysts using QCEW to measure “total employment” in a county should be aware that sectors with high rates of self-employment — agriculture, construction, professional services — will be systematically undercounted relative to the true labor force.

Geographic Granularity: The Core Advantage

QCEW publishes data at five geographic levels: national, state, metropolitan statistical area (MSA), county, and congressional district. The county-level data is the most significant. The United States has over 3,100 counties and county-equivalents, and QCEW provides employment and wage statistics for each of them, broken down by industry.

This is genuinely rare. The CES payroll survey publishes monthly employment for roughly 450 metropolitan areas but has no county data. The American Community Survey provides occupation and earnings data at the county level but is a five-year sample with substantial margins of error for small counties. QCEW, by contrast, is a near-census of all establishments, so even a county with 8,000 total jobs produces statistically reliable counts rather than estimates.

The county-industry combination is what makes QCEW uniquely powerful for local economic development analysis: you can see exactly how many workers in Breathitt County, Kentucky work in mining (NAICS 21), what their average weekly wages are, and how both figures have trended since 2000.

Industry Classification: NAICS from Sector to Six Digits

QCEW uses the North American Industry Classification System (NAICS). Data is available at every level of the NAICS hierarchy:

Finer industry codes are suppressed at smaller geographies to protect the confidentiality of individual employers. The suppression rules are discussed below.

Key Data Fields

Each QCEW record is identified by four keys:

The primary measures are:

The annual QCEW file adds average annual pay — total annual wages divided by annual average employment — which is the most commonly cited wage metric in economic development reports.

Suppression Rules and Disclosure Avoidance

BLS suppresses a cell when publishing it would disclose information about an individual employer. The primary trigger is when an industry-area-ownership combination has fewer than three establishments or when a single employer accounts for 80% or more of the employment in that cell. Suppressed cells appear in the data with a flag code rather than a numeric value.

The practical effect is significant for small counties. A rural county with one semiconductor fab may have its manufacturing employment suppressed entirely at the 6-digit NAICS level, and potentially at the 4- or 5-digit level too if that fab is the dominant employer. Analysts working with fine-grained county-industry data should always check suppression flags before computing statistics and should roll up to coarser industry codes or aggregate across time when suppressed counts are material.

State-level and national-level data are almost never suppressed. MSA-level suppression is uncommon. County suppression becomes frequent for industries employing fewer than a few hundred workers in a given county.

How QCEW Differs from CES and LAUS

Three BLS programs collectively describe the US labor market. Their relationships are worth understanding precisely.

Current Employment Statistics (CES) — also called the payroll survey or nonfarm payroll survey — is the monthly jobs report that moves financial markets. CES surveys roughly 119,000 businesses each month and publishes national, state, and metro-area employment by major industry with a lag of roughly two weeks after the reference month. CES is fast and authoritative at the aggregate level, but it has no county data and its industry detail stops at the 3- or 4-digit NAICS level. Critically, QCEW is the benchmark that CES estimates are calibrated to. Once per year BLS publishes a CES benchmark revision that re-anchors the monthly sample to the prior year's QCEW counts. If QCEW shows that CES overestimated employment by 800,000 jobs over the prior year, those jobs disappear in the benchmark revision. QCEW is the ground truth; CES is the timely estimate.

Local Area Unemployment Statistics (LAUS) produces monthly unemployment rates for every state, county, and sub-county area. LAUS is a model-based program that combines inputs from CPS, CES, UI claims data, and QCEW to produce labor force and unemployment estimates at geographic levels where direct survey data is too sparse to be reliable. LAUS gives you unemployment rates down to the city level; QCEW gives you employment and wages by industry down to the county level. Neither alone is sufficient for comprehensive local labor market analysis — both together tell a much richer story.

Wage Data: What You Can Actually Measure

Average weekly wages by county and industry are one of the most analytically valuable outputs of QCEW. Because the data spans decades (QCEW annual files go back to 1975 in many areas) and covers every county, you can make comparisons that no survey could support:

The wage figures are gross wages, not adjusted for cost of living, hours worked, or worker characteristics. Pairing QCEW wages with ACS occupation and demographic data enables finer comparisons, but the raw QCEW wage series is already diagnostic for many economic development questions.

Applications

Local economic development. Site selectors and economic development organizations use QCEW to profile the existing industry mix of a county, identify clusters of related industries, and measure the concentration of specific sectors relative to the national average (location quotient analysis).

Plant closure and opening impact. QCEW is the standard data source for measuring employment displacement following a mass layoff and for validating ex-ante projections of job creation from a new facility. The quarterly frequency and county granularity make it possible to see effects within a year of a closure or announcement.

Industry geographic distribution. Mapping which counties host semiconductor fab employment (NAICS 334413), pharmaceutical manufacturing (NAICS 325412), or data center operations (NAICS 518210) reveals the geographic concentration of strategic industries and informs supply chain vulnerability analysis, infrastructure investment priorities, and workforce training program design.

Shift-share analysis. Decomposing employment change into national growth, industry mix, and local competitive effects requires county-level employment by industry at two points in time. QCEW is the standard input to shift-share models used in regional economics.

Wage inequality research. Between-county and within-county wage dispersion by industry — tracked annually over decades — documents the spatial dimension of rising wage inequality in ways that national survey data cannot.

How to Access QCEW

BLS publishes QCEW data through several channels:

Python: County-Level Wages by Industry for Kentucky

The following script downloads the 2023 annual QCEW file for Kentucky, filters to private-sector establishments, computes total employment and employment-weighted average weekly wages at the 3-digit NAICS level for each county, and returns the five highest-wage industries per county.

import requests
import pandas as pd

# Download QCEW annual data for a single state (FIPS 21 = Kentucky)
# Annual file gives establishment counts, employment, wages, and avg annual pay
STATE_FIPS = "21"
YEAR = "2023"

url = (
    "https://data.bls.gov/cew/data/files/"
    + YEAR
    + "/csv/"
    + YEAR
    + "_annual_by_area.zip"
)

# BLS bulk files are ZIP archives containing one CSV per area
import io, zipfile, re

resp = requests.get(url, timeout=120)
resp.raise_for_status()

# Find the file for our state inside the ZIP
target_pattern = re.compile(r"^" + YEAR + r"." + STATE_FIPS + r".Annual.By_Area.csv$")

with zipfile.ZipFile(io.BytesIO(resp.content)) as zf:
    matches = [n for n in zf.namelist() if target_pattern.match(n)]
    if not matches:
        raise FileNotFoundError("State FIPS not found in archive.")
    with zf.open(matches[0]) as f:
        df = pd.read_csv(f, dtype=str)

# Numeric columns
num_cols = [
    "annual_avg_estabs",
    "annual_avg_emplvl",
    "total_annual_wages",
    "avg_annual_pay",
]
for col in num_cols:
    df[col] = pd.to_numeric(df[col], errors="coerce")

# Keep only private-sector rows (own_code == 5) with a valid NAICS code
private = df[(df["own_code"] == "5") & df["industry_code"].notna()].copy()

# Extract 3-digit NAICS from the industry_code field
private["naics3"] = private["industry_code"].str[:3]

# Filter to rows where industry_code IS the 3-digit code (length == 3)
sector3 = private[private["industry_code"].str.len() == 3].copy()

# County-level rows have a 5-digit area_fips; statewide rows are 5-char ending in 000
county = sector3[
    sector3["area_fips"].str.len() == 5
    & ~sector3["area_fips"].str.endswith("000")
].copy()

# Compute average weekly wage = total annual wages / (annual avg employment * 52)
county["avg_weekly_wage"] = (
    county["total_annual_wages"] / (county["annual_avg_emplvl"] * 52)
).round(2)

# Drop rows with zero employment (suppressed or genuinely zero)
county = county[county["annual_avg_emplvl"] > 0].dropna(subset=["avg_weekly_wage"])

# Aggregate: total employment and employment-weighted avg weekly wage by county + 3-digit NAICS
agg = (
    county.groupby(["area_fips", "area_title", "naics3"])
    .apply(
        lambda g: pd.Series(
            {
                "total_estabs": g["annual_avg_estabs"].sum(),
                "total_employment": g["annual_avg_emplvl"].sum(),
                "avg_weekly_wage": (
                    (g["avg_weekly_wage"] * g["annual_avg_emplvl"]).sum()
                    / g["annual_avg_emplvl"].sum()
                ),
            }
        ),
        include_groups=False,
    )
    .reset_index()
)

# Top 5 highest-wage 3-digit industries per county
top5 = (
    agg.sort_values(["area_fips", "avg_weekly_wage"], ascending=[True, False])
    .groupby("area_fips")
    .head(5)
    .reset_index(drop=True)
)

print(top5[["area_title", "naics3", "total_employment", "avg_weekly_wage"]].head(25).to_string(index=False))

A few notes on the implementation. The BLS bulk annual files are structured as one CSV per state inside a ZIP archive. The area_fips field encodes geography: a 5-digit code ending in “000” is a statewide total; a 5-digit code not ending in “000” is a county. The own_code field distinguishes private (5) from government ownership. Suppressed cells contain BLS flag codes rather than numeric values, which become NaN after pd.to_numeric(..., errors='coerce')— the final filter on positive employment removes them naturally.

This pattern extends directly to all 50 states by changing the FIPS constant, to multi-year trend analysis by looping over years, and to finer industry detail by filtering to industry codes of length 4 or 6 rather than 3 (subject to suppression at finer levels for small counties).

Connecting QCEW to Other Federal Datasets

QCEW's county-industry-wage structure connects naturally to several other federal datasets:

Limitations and Practical Cautions

The five-month publication lag is the most operationally significant limitation. If a plant closes in January, the first QCEW data confirming the employment loss will appear in June. For policy response and economic monitoring, CES and UI claims data fill the gap; QCEW provides the definitive county-level picture after the fact.

Geography in QCEW follows the establishment's physical location, not the employer's headquarters. A national retailer's distribution center in rural Nevada appears in Nevada's county data, not in the state where the company is headquartered. This is the correct treatment for local labor market analysis — workers commute to the establishment, not the headquarters — but analysts constructing firm-level industry profiles from QCEW should be aware that multi-state employers will be spread across many county cells.

Wage figures in QCEW do not distinguish full-time from part-time workers. Average weekly wages will be depressed in industries with high part-time shares — retail trade, food service, arts and entertainment — relative to industries where full-time work is the norm. Converting to an hourly wage requires the BLS OES (Occupational Employment and Wage Statistics) program, which reports occupational wage rates but lacks the geographic granularity and temporal depth of QCEW.


The BLS Job Openings and Labor Turnover Survey (JOLTS) complements QCEW with monthly data on job openings, hires, and separations by industry — the demand-side counterpart to QCEW's supply-side employment census. See BLS JOLTS: Measuring Labor Demand Through Job Openings and Turnover.

Price-adjusting QCEW wages over time requires a consumer price index. The BLS CPI-U is the standard deflator for nominal wage series. See BLS CPI-U: The Consumer Price Index for All Urban Consumers.

For county-level demographic context — occupation distribution, educational attainment, and earnings by worker characteristics — pair QCEW with the Census Bureau's American Community Survey. See Census ACS: County-Level Demographic and Economic Data.