What Is a Shapefile?
The Shapefile is the most widely deployed vector geospatial data format in the world — and it is not a single file. Introduced by ESRI in 1994 alongside ArcView GIS 2, a Shapefile is actually a bundle of files sharing the same base name but different extensions, all of which must travel together for the data to be usable.
Despite its age and well-documented limitations, the Shapefile remains the lingua franca of geospatial data exchange. Government agencies, OpenStreetMap exports, Census Bureau TIGER files, natural resource agencies, and transportation departments all distribute data in Shapefile format. Understanding it is unavoidable for anyone working with GIS.
The File Bundle
A complete Shapefile requires at minimum three files:
| Extension | Role | Format |
|---|---|---|
.shp |
Geometry storage — coordinates of features | Binary |
.dbf |
Attribute table — rows of data for each feature | dBASE IV |
.shx |
Spatial index — byte offsets into the .shp file | Binary |
And commonly includes:
| Extension | Role |
|---|---|
.prj |
Coordinate Reference System as WKT string |
.cpg |
Code page declaration for .dbf text encoding (e.g., UTF-8) |
.qpj |
QGIS extended PRJ with more complete CRS metadata |
.sbn / .sbx |
Spatial index for ArcGIS performance |
.xml |
ISO 19139 metadata |
If you receive a .shp file without its .dbf companion, you have geometry but no attribute data. If you are missing the .prj, software will ask you to specify the coordinate system manually — a common source of projection mismatch errors.
Geometry Types
Shapefile supports exactly one geometry type per file:
| Type Code | Geometry | Example Use |
|---|---|---|
| 1 | Point | City locations, sample sites, GPS waypoints |
| 3 | Polyline (MultiLineString) | Roads, rivers, pipelines, contours |
| 5 | Polygon (MultiPolygon) | Countries, parcels, land use zones |
| 8 | MultiPoint | Point clouds, earthquake epicenters |
| 11 | PointZ | 3D points with elevation |
| 13 | PolylineZ | 3D paths — tunnels, flight tracks |
| 15 | PolygonZ | 3D surfaces — building footprints with height |
| 21 | PointM | Measured points — milepost markers |
A single Shapefile cannot mix geometry types — all roads must go in one file, all polygons in another. This is a fundamental limitation that trips up new GIS users.
The DBF Attribute Table
The .dbf (dBASE IV) file stores attribute data for each geometry:
- Maximum 10 characters per field name — the single most complained-about Shapefile limitation
- Maximum 255 bytes per text field value
- Maximum 2,147,483,647 records (2 GB file size ceiling)
- No native support for Unicode in the original spec (
.cpgfile partially addresses this) - No support for NULL values in integer/float fields (stored as 0, which is ambiguous)
- No date-time type — only date (YYYYMMDD)
These constraints mean attributes like "CountyName" become "CNTYNM" and "PopulationDensityPerSquareKilometer" becomes "PDPSKM" — completely opaque abbreviations that require a separate data dictionary to interpret.
The .prj Projection File
The projection file contains a Well-Known Text (WKT) string describing the Coordinate Reference System:
GEOGCS["GCS_WGS_1984",
DATUM["D_WGS_1984",
SPHEROID["WGS_1984",6378137.0,298.257223563]],
PRIMEM["Greenwich",0.0],
UNIT["Degree",0.0174532925199433]]
Without this file, software must guess the CRS — often defaulting to WGS84. When the actual data is in a projected system (UTM, State Plane, ETRS89), features will appear in the wrong location or at the wrong scale. Always distribute the .prj file alongside your Shapefile.
Reading Shapefiles in Python
GeoPandas (the standard library for vector GIS in Python):
import geopandas as gpd
# Read a Shapefile
gdf = gpd.read_file("countries.shp")
print(gdf.crs) # coordinate reference system
print(gdf.dtypes) # column types
print(gdf.head()) # first few rows including geometry
# Spatial query — select features that intersect a bounding box
from shapely.geometry import box
bbox = box(-10, 35, 30, 70) # roughly Europe
europe = gdf[gdf.intersects(bbox)]
# Reproject to Web Mercator for tiled mapping
gdf_mercator = gdf.to_crs(epsg=3857)
# Write back as Shapefile
gdf_mercator.to_file("countries_mercator.shp")
# Write as GeoJSON instead
gdf_mercator.to_file("countries.geojson", driver="GeoJSON")
Fiona (lower-level, closer to OGR):
import fiona
with fiona.open("countries.shp") as src:
print(src.crs)
print(src.schema) # geometry type + field types
for feature in src:
geom = feature["geometry"]
props = feature["properties"]
print(props["NAME"], geom["type"])
Converting Shapefiles with ogr2ogr
# Shapefile → GeoJSON
ogr2ogr -f GeoJSON countries.geojson countries.shp
# Shapefile → GeoPackage (modern replacement)
ogr2ogr -f GPKG countries.gpkg countries.shp
# Shapefile → PostGIS
ogr2ogr -f "PostgreSQL" PG:"host=localhost dbname=gis user=postgres" \
countries.shp -nln countries -overwrite
# Reproject on the fly (from EPSG:4326 to EPSG:3857)
ogr2ogr -f "ESRI Shapefile" countries_mercator.shp countries.shp \
-s_srs EPSG:4326 -t_srs EPSG:3857
# Filter by attribute
ogr2ogr -f GeoJSON europe.geojson countries.shp -where "CONTINENT='Europe'"
# Clip to bounding box
ogr2ogr -f "ESRI Shapefile" clipped.shp input.shp \
-clipsrc -10 35 30 70
Why Move to GeoPackage?
GeoPackage (.gpkg) is the OGC-standardized SQLite-based replacement for Shapefile:
| Feature | Shapefile | GeoPackage |
|---|---|---|
| Single file | No (bundle) | Yes (one .gpkg) |
| Max field name | 10 characters | 1000+ characters |
| Max file size | 2 GB | 140 TB |
| Multiple layers | One per file set | Multiple in one file |
| Unicode support | Partial (.cpg) | Full UTF-8 |
| Geometry types | Single type per file | Mixed per layer |
| NULL values | Ambiguous (0) | True NULL |
| Date-time support | Date only | Full datetime |
| Raster support | No | Yes (tiles) |
QGIS, ArcGIS Pro, GDAL, and PostGIS all support GeoPackage natively. The US National Geospatial-Intelligence Agency (NGA) mandated GeoPackage as the preferred format for geospatial data exchange in 2021. For new projects, GeoPackage is almost always the better choice.
Working with the US Census TIGER Shapefiles
The US Census Bureau distributes TIGER/Line Shapefiles — the authoritative dataset for US administrative boundaries, roads, and demographic geography:
# Download 2023 counties Shapefile
wget https://www2.census.gov/geo/tiger/TIGER2023/COUNTY/tl_2023_us_county.zip
unzip tl_2023_us_county.zip
# Inspect with ogrinfo
ogrinfo -al -so tl_2023_us_county.shp
# Convert to GeoJSON, keeping only a few fields
ogr2ogr -f GeoJSON counties.geojson tl_2023_us_county.shp \
-select "NAME,STATEFP,COUNTYFP,ALAND,AWATER"
The TIGER files use EPSG:4269 (NAD83) — not WGS84. The difference is sub-meter for most applications, but for precision surveying or alignment with GPS data, you may need to reproject.
Shapefile Size Limits in Practice
The 2 GB limit applies separately to the .shp and .dbf files. A Shapefile with complex polygon geometries (coastlines, watershed boundaries) can exhaust the 2 GB .shp limit without having many features. The OpenStreetMap full-planet Shapefile exports routinely exceed this limit and must be split by geographic region or converted to GeoPackage or PostGIS for practical use.
Shapefile cannot represent topology — shared boundaries between adjacent polygons are stored as duplicate coordinate sequences, leading to slivers and gaps after independent editing of adjacent features. Formats like PostGIS enforce topology explicitly; Shapefile never has and never will.
Related conversions
Frequent conversions across the catalogue: