Files & formats
Reading and writing shapefiles, GeoPackages, GeoJSON and CSV — and what breaks in each.
A spatial file is a container with opinions. Shapefile truncates field names at ten characters and cannot store a datetime. GeoJSON is always WGS 84, whatever you had. GeoPackage takes almost anything and puts it in one file. Reading is rarely the problem — GDAL handles around 200 vector formats behind one interface — so the work here is identification, selection, and knowing what a round trip costs.
The failures are mostly silent. A GeoPackage holding several layers hands you the first one. A shapefile copied without its .dbf opens with no attributes. A missing .prj gives you crs = None, which is not a bug but information that was lost at the moment somebody copied the file. None of these raise anything.
Below, the concepts cover what the formats are and what each one can carry, the how-to guides are one per format plus the conversions between them, and the fixes are the specific errors each format produces.
🧭 Start with the concepts
The ideas the how-to guides below assume you already have.
- WKT, WKB and GeoJSON: How Geometry Is Actually Stored
- GIS Vector File Formats Compared: Shapefile, GeoPackage, GeoJSON, Parquet
- What GDAL and OGR Actually Are (and Why Everything Depends on Them)
- Fiona vs pyogrio: How GeoPandas Reads and Writes Files
- QGIS Data Providers Explained: How QGIS Reads Any Data Source
- PostGIS Explained: When a Spatial Database Beats a Folder of Files
Show every concept in this topic
- How PostGIS Stores Geometry: SRID, EWKB and the Typed Column
- The Raster Data Model Explained: Bands, dtype, NoData and the Transform
- GeoParquet and Columnar Storage Explained: Why It Reads So Much Faster
- The OpenStreetMap Data Model Explained for Python Users
- Spatial Web Services Explained: WFS, WMS and OGC API Features
- LAS, LAZ and COPC Explained: How Point Clouds Are Stored
- PMTiles and MBTiles Explained: Tile Archives Without a Server
- GeoJSON, Vector Tiles or Parquet: Choosing an API Response Format
- NetCDF and Gridded Data Explained: Dimensions, Variables and Attributes
- CF Conventions Explained: How a NetCDF File Says What Its Numbers Mean
- GRIB, NetCDF or Zarr: Choosing a Format for Gridded Data
- Level of detail explained for 3D city models
- CityJSON and CityGML explained
- GTFS explained: the tables behind every transit feed
- GTFS service calendars explained: calendar, calendar_dates and the service day
- Sentinel-1 products explained: SLC, GRD and radiometrically terrain-corrected
- OpenStreetMap File Formats Explained: PBF, XML and the Rest
⚙️ Then do the task
Step-by-step walkthroughs with code you can copy and adapt.
- How to Read GeoJSON in Python with GeoPandas
- How to Read a CSV with Coordinates as a GeoDataFrame
- How to Read and Write GeoPackage Files in Python
- How to Connect GeoPandas to PostGIS
- How to Read a Shapefile in Python with GeoPandas
- How to Export GeoJSON in Python with GeoPandas
Show every how-to guide in this topic
- How to Clean Messy CSV Coordinates into a Reliable GeoDataFrame
- How to Batch Convert Shapefiles to GeoPackage in Python
- How to Merge Many Shapefiles into One File in Python
- How to Batch Export a GeoDataFrame to Multiple Formats in Python
- How to Move Data Between QGIS and GeoPandas
- How to Reduce GIS File Size in Python Without Wrecking the Data
- How to Package GIS Deliverables into Zipped Bundles with Python
- How to Write a GeoDataFrame to PostGIS
- How to Set Up a Python GIS Environment That Actually Works
- How to Standardise Attribute Values Against a Controlled Vocabulary
- How to Test a GIS Script That Reads and Writes Files
- How to Work with a Custom or Local CRS in Python
- How to Open Any Spatial File in Python When You Do Not Know the Format
- How to Download OpenStreetMap Data in Python with OSMnx
- How to Query the Overpass API from Python
- How to Download Data from a WFS Service in Python
- How to Read a LAS or LAZ File in Python with laspy
- How to Write Partitioned GeoParquet and Query It with Filters
- How to Load GPS Tracks into Python as Trajectories
- How to Read Shapefiles, GeoJSON and GeoParquet in DuckDB
- How to Add a Download Button for Filtered Spatial Data
- How to Open a NetCDF File in Python with xarray
- How to Convert NetCDF to GeoTIFF in Python
- How to Read GRIB Weather Forecast Data in Python
- How to Compact an H3 Cell Set to Store a Region Cheaply
- How to Download Census Boundaries in Python
- How to strip GPS coordinates from photo metadata in Python
- How to write a metadata record for a dataset in Python
- How to read the metadata already inside your spatial files
- How to store metadata inside a GeoPackage
- How to read a CityJSON city model in Python
- How to export a 3D city model to glTF in Python
- How to write a variable-rate prescription map
- How to read a GTFS feed in Python
- How to Read an OpenStreetMap PBF File in Python
- How to Export OpenStreetMap Data to GeoPackage or Shapefile in Python
🔧 When it breaks
The errors this topic produces, with the cause explained rather than just the command.
- GeoPandas Not Reading Shapefile: Common Causes and Fixes
- Why Are My Shapefile Column Names Truncated? How to Fix It
- RasterioIOError: Not Recognized as a Supported File Format (How to Fix)
- GeoPandas "No Geometry Column" Error: How to Fix It
- Python glob Is Not Finding All My Shapefiles: How to Fix It
- Garbled Attribute Text and UnicodeDecodeError from a Shapefile: How to Fix Encoding
Show every fix in this topic
- GeoPandas to_file() Fails on a Column Type: How to Fix It
- Mixed Geometry Types Error When Saving a GeoDataFrame: How to Fix It
- Rasterio Output GeoTIFF Is Black or Empty: How to Fix It
- PostGIS "relation does not exist" and Permission Errors: How to Fix Them
- GeoJSON Downloaded from an API Is Empty or Truncated
- A LAZ File Will Not Open in Python
- GDAL Cannot Open an S3 or HTTPS Path
- Fixing Addresses That Break on Accents and Encoding
- Fixing Missing or Substituted Fonts in an Exported Map PDF
- Fixing ST_Read Failures on Spatial Files in DuckDB
- Fixing a Geometry Column Lost on Export from DuckDB
- Fixing an Uploaded File That Breaks a Map App
- Fixing xarray's "Did Not Find a Match in Any of xarray's Installed Backends"
- Fixing Census Joins That Fail Because Leading Zeros Were Dropped
- A shared file still contains the original coordinates
- Metadata disappears when you convert the file
- A prescription map is rejected by the machine controller
- M values are lost when you export the route
- Why Does My FARS Code Break When I Change the Year?
- Fixing SST Values That Read as Thousands Instead of Degrees
- Fixing Coordinates That Lose Precision When Saved to a File
- Fixing OpenStreetMap Features Counted Twice as Lines and Polygons
Learning paths through this topic
A curated route rather than a list — the guides in the order that builds on itself.
- Finding & Fetching Data
- Raster Analysis
- Spatial SQL & PostGIS
- GIS Data Cleaning
- Batch Processing
- QGIS Automation
- LiDAR & Point Clouds
- Cloud-Native GIS
- Publishing Web Maps
- Movement & Time
- Geocoding & Addresses
- Cartography & Map Design
- DuckDB for Spatial Data
- Serving Spatial Data
- Maps, Apps & Dashboards
- Gridded & Climate Data
- H3 & Global Grids
- Census & Demographics
- Geoprivacy & Anonymisation
- Metadata, Licensing & Provenance
- 3D & Buildings
- Agriculture & Crops
- Public Transit & GTFS
- Radar & SAR Imagery
- Linear Referencing
Related topics
Subjects that keep coming up alongside this one, most overlap first.