53033 FipsDecoder

FIPS Codes vs GEOID: What's the Difference?

If you've worked with Census data, you've probably seen both "FIPS code" and "GEOID" used to identify geographic areas — sometimes for the same place. They're closely related but not identical, and conflating them is a common source of data-join bugs.

The Short Answer

A GEOID is the Census Bureau's own notation for a geographic identifier. For most geography types, a GEOID is simply a concatenation of the relevant FIPS codes, zero-padded to a fixed total length.

King County, Washington

State FIPS 53 (Washington)
County FIPS 53033 (state 53 + county 033)
Census Tract GEOID 53033005302 (state + county + tract 005302)
Block Group GEOID 530330053021 (state + county + tract + block group 1)
Census Block GEOID 5303300530211001 (15 digits total)

At the county level, the GEOID and the 5-digit county FIPS code are the same thing. The distinction matters when you're working below the county level — with Census tracts, block groups, or blocks — where GEOIDs grow longer by concatenating more FIPS components.

GEOID Length by Geography Type

Geography GEOID Length Formula
State2 digitsState FIPS
County5 digitsState FIPS (2) + County FIPS (3)
Census Tract11 digitsState (2) + County (3) + Tract (6)
Block Group12 digitsState (2) + County (3) + Tract (6) + BG (1)
Census Block15 digitsState (2) + County (3) + Tract (6) + Block (4)
Place7 digitsState (2) + Place (5)
ZCTA (ZIP area)5 digitsZCTA code (5) — not a ZIP code

The Most Common Gotcha: Tract GEOIDs in Census Data

When you download Census ACS data at the tract level, the GEO_ID column typically looks like 1400000US53033005302 — with a prefix indicating the geographic summary level. The numeric part after US is the GEOID. Strip the prefix before joining to other datasets.

import pandas as pd

df = pd.read_csv('census_tract_data.csv', dtype=str)

# GEO_ID looks like "1400000US53033005302" — strip the prefix
df['geoid'] = df['GEO_ID'].str.replace(r'^.*US', '', regex=True)

# Now extract components
df['state_fips']  = df['geoid'].str[:2]
df['county_fips'] = df['geoid'].str[:5]
df['tract_code']  = df['geoid'].str[5:11]

ZCTAs Are Not ZIP Codes

One additional source of confusion: the Census Bureau uses ZCTAs (ZIP Code Tabulation Areas), which are Census-defined approximations of USPS ZIP codes. ZCTA codes look like ZIP codes (5 digits) but are not the same — a few thousand ZIP codes have no ZCTA equivalent, and ZCTA boundaries can differ from the actual postal delivery area.

For geographic analysis, always use FIPS codes. ZCTAs are an approximation of ZIP codes, not a substitute for county FIPS codes.