The shapefile format, explained
A shapefile isn't a single file. It's a small set of files that work together: the .shp holds geometry, the .shx indexes it, the .dbf stores attributes, and the .prj records the coordinate system. This guide walks through each piece, how the data is actually stored, the format's real-world limits, and why it's still everywhere decades later.
What a shapefile is
The shapefile is the closest thing GIS has to a universal format. Esri created it in the early 1990s for its ArcView software and published it as an open specification, and being both good enough and open is what made it the format nearly every mapping tool learned to read and write. Thirty years on, it's still the default way governments, surveyors, and data providers hand geospatial data to each other.
The name is misleading. A "shapefile" is really a group of files sharing one base name and different extensions, kept together in the same folder. Separate any one of them and you may have a problem. Below is what each file does, how the data inside is organized, and where the format shows its age.
The files that make up a shapefile
.shp— the geometry itself: the raw coordinates of every point, line, or polygon. This is the heart of the shapefile..shx— a positional index that records where each shape begins inside the.shp, so software can jump to feature number 5,000 without reading the first 4,999..dbf— the attribute table: one row per shape, with columns of data (names, IDs, measurements). It's a dBASE database file..prj— the coordinate reference system, written as a WKT (Well-Known Text) string. It tells software what the coordinates mean..cpg(optional) — declares the character encoding of the.dbftext, so accented and non-Latin characters read correctly..sbn/.sbx(optional) — a spatial index Esri software uses to speed up queries..xml(optional) — metadata about the dataset (source, accuracy, description).
The first three (.shp, .shx, .dbf) are the mandatory core; the .prj is strongly recommended. The rest are conveniences.
How geometry is stored
The .shp file opens with a fixed 100-byte header: a magic number, the overall bounding box, and a single shape type for the entire file. Every feature that follows is a record, made of a small header (record number and length) plus the coordinates for that shape.
A shapefile holds one geometry type throughout. The common ones are:
- Point — a single X/Y location, like a well or a sample site.
- Polyline — one or more connected paths, like a road or a river.
- Polygon — closed rings that bound an area such as a parcel, lake, or county.
- MultiPoint — a set of points treated as one feature.
Lines and polygons can be made of multiple parts. A polygon feature can have several rings: an outer ring for the boundary and inner rings for holes, with ring direction (clockwise vs. counter-clockwise) signalling which is which. There are also "M" and "Z" variants that add a measure value or an elevation to each coordinate, for 3D and linear-referencing data.
How attributes work (the .dbf)
Every shape lines up with exactly one row in the .dbf, matched purely by order: the first geometry pairs with the first record, and so on. The .dbf is a fixed-width dBASE table. Each field has a declared type (character, numeric, date, logical) and a fixed byte width, so record n sits at a predictable offset. That fixed layout is what makes attribute reads fast, and it's also the source of the format's best-known quirks (below).
The projection file (.prj)
The .prj holds one WKT string describing the coordinate reference system: the datum, the projection, and its parameters. This is what lets software place your coordinates correctly on the Earth. Data in a projected system such as UTM or State Plane has coordinates in meters or feet that mean nothing without the .prj to interpret them. When a shapefile arrives without one, tools have to assume a CRS, often WGS84 lon/lat, and if that guess is wrong, the data lands in the wrong spot. (Maptinker reads the .prj and reprojects projected data to lon/lat on load so it aligns with web basemaps.)
Real-world limits
The shapefile's age comes with hard constraints worth knowing before you commit data to it:
- 2 GB per file — a 32-bit byte offset caps both the
.shpand.dbfat 2 GB each. - 10-character field names — inherited from dBASE; longer column names get silently truncated, which can collide.
- One geometry type per file — you can't mix points and polygons in a single shapefile.
- No topology — shapes are stored independently, so shared borders are duplicated and there's no built-in notion of adjacency.
- DBF data-type quirks — limited numeric precision, awkward handling of long text, no true null for many field types, and encoding ambiguity unless a
.cpgis present. - The multi-file burden — losing the
.prjor.dbfdegrades or breaks the dataset, and the pieces are easy to separate.
Why the shapefile persists despite its age
For all those limits, the shapefile is hard to kill, for good reasons. It's genuinely universal: essentially every GIS tool ever written reads and writes it, so it's the safest bet for handing data to someone whose software you don't know. It's simple and openly documented. And thirty years of accumulated data (public parcels, census geographies, agency datasets) already lives in this format. Universal support plus that much existing data keeps it in daily use.
Modern alternatives
When the limits start to bite, newer formats each fix a specific pain point:
- GeoJSON — a single human-readable text file, native to the web; ideal for sharing and web maps, though verbose for large data.
- FlatGeobuf — a compact binary format with a built-in spatial index; fast to stream and read, one file, no size ceiling in practice.
- GeoParquet — columnar storage built for analytics and very large datasets, at home in modern data pipelines.
A practical rule: keep shapefiles for interchange with unknown tools, and reach for one of these when you need the web, speed, or scale. If you just want to see a shapefile, or turn it into GeoJSON, you can do both in your browser with no install required.