# Fiona: a Pythonic face on GDAL, with the wheel's format limits stated up front

> Fiona reads and writes vector geospatial data by wrapping GDAL's vector API in a small Python interface where features are plain data classes modelled on GeoJSON. Its install story is the part to read first, because the PyPI wheels are aimed at simple applications and deliberately omit many of GDAL's optional format drivers, which is why GML support needs a source build or conda.

**Toblerity/Fiona** — Fiona reads and writes geographic data files

- Repository: https://github.com/Toblerity/Fiona
- Website: https://fiona.readthedocs.io/
- Stars: 1,249 · Forks: 222
- Language: Python
- License: BSD-3-Clause
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/toblerity-fiona

## A wrapper that stops at the GDAL boundary

Fiona streams simple feature data to and from GIS formats like GeoPackage and Shapefile, and can read and write real-world data using multi-layered GIS formats, zipped and in-memory virtual file systems, from files on your hard drive or in cloud storage.

The relationship to GDAL is stated with unusual clarity in the README. Fiona depends on GDAL but is different from GDAL's own bindings, and the stated reason is that Fiona is designed to be highly productive and to make it easy to write code which is easy to read.

That is a design statement about surface area rather than capability. The GDAL Python bindings expose a wide API faithfully, including the parts that are awkward. Fiona exposes the part that a data-processing script actually needs, with data classes instead of binding objects, and a driver configuration you set once rather than per call.

The repository description says Fiona reads and writes geographic data files, and the package description in pyproject.toml says Fiona reads and writes spatial data files. The distinction from GDAL's bindings is the whole product.

The topic list names gdal, ogr, gis, vector, cython and python. OGR is the vector part of GDAL, so the dependency is on one half of a large C library rather than all of it.

## Features are data classes, and geometry is somebody else's job

The Python usage section is precise about the division of responsibility. Features are read from and written to file-like Collection objects returned from the fiona.open() function, and features are data classes modeled on the GeoJSON format. They don't have any spatial methods of their own, so if you want to transform them you will need Shapely or something like it.

That is the key design decision. A feature in Fiona is essentially a dict with a geometry and a properties mapping, and it is not the place where geometry algorithms live. Shapely is. The two libraries are complementary, and the Fiona example in the README is written to show that, opening a source, filtering, computing a centroid with shape() from Shapely, converting it back with Geometry.from_dict, and writing it out.

The mapping is therefore explicit. Fiona handles the file format, the schema and the coordinate reference system, and Shapely handles the geometry. A team that expects Fiona alone to answer spatial questions will find the answer one dependency away, and the README says so rather than leaving it to be discovered.

The profile mechanism is the other part of the interface worth understanding. The profile is a mapping carrying the coordinate system, the format driver name and the record schema, and it can be taken from the source and then modified, which is how the example changes the geometry type to Point and the driver to GPKG before opening the output file.

## The wheel is the limitation, and the README says so

The installation section contains the most important caveat in the project, and it is unusually blunt about it.

Fiona has several extension modules which link against libgdal. This complicates installation. Binary distributions containing libgdal and its own dependencies are available from the Python Package Index and can be installed using pip.

Then the part to read twice. These wheels are mainly intended to make installation easy for simple applications, not so much for production. They are not tested for compatibility with all other binary wheels, conda packages, or QGIS, and they omit many of GDAL's optional format drivers.

That is a specific limitation with a specific consequence. If you need, for example, GML support, you will need to build and install Fiona from a source distribution. And the compatibility caveat is not about Fiona alone, it is about the whole binary stack: a wheel that bundles its own libgdal is not tested against other binary wheels, conda packages or QGIS.

Two escape hatches are given. It is possible to install Fiona from source using pip, version 22.3 or later, with the --no-binary option, and a specific GDAL installation can be selected by setting the GDAL_CONFIG environment variable. Many users find Anaconda and conda-forge a good way to install Fiona and get access to more optional format drivers, like GML.

For a team standardising on conda, that is the path. For a team standardising on pip in a clean container, the source build with a pinned GDAL is the path. The wheel is the convenience route, and the README says the convenience route is the one that omits drivers.

## The Python API in full, with a bbox filter

The example in the README is the API in miniature, and it packs a lot into thirty lines.

```python
import fiona
from fiona import Feature, Geometry
from shapely.geometry import mapping, shape

with fiona.open(
    "zip+https://github.com/Toblerity/Fiona/files/11151652/coutwildrnp.zip"
) as src:

    profile = src.profile
    profile["schema"]["geometry"] = "Point"
    profile["driver"] = "GPKG"

    with fiona.open("centroids.gpkg", "w", **profile) as dst:

        for feat in src.filter(bbox=(-107.0, 37.0, -105.0, 39.0)):

            centroid_shp = shape(feat.geometry).centroid
            new_geom = Geometry.from_dict(centroid_shp)

            dst.write(
                Feature(geometry=new_geom, properties=f.properties)
            )
```

Three things stand out.

The URL is a virtual file system path. The string begins with zip+https, so Fiona is asked to fetch a zip archive over HTTPS and read the shapefile inside it. That is the same mechanism that handles /vsizip/ paths and in-memory buffers, and it is why the README mentions zipped and in-memory virtual file systems, and cloud storage in the same breath as your hard drive.

The filter is a server-side pushdown. src.filter(bbox=...) restricts the features processed to those intersecting the box, and the driver does the work rather than the Python loop. On a large shapefile that is the difference between reading the whole file and reading a fraction of it.

The context managers handle the flushing. The README points out that the destination's contents are flushed to disk and the file is closed when the with block ends, which effectively executes dst.flush() and dst.close(). That is a detail, but it is the kind of detail that decides whether a partially written output file exists after a crash.

## fio cat, and the CLI as a second front end

Fiona's command line interface is named fio, and it is documented separately in docs/cli.rst. The README highlights one command, fio cat, which streams GeoJSON features from any dataset.

```console
$ fio cat --compact tests/data/coutwildrnp.shp | jq -c '.'
{"geometry":{"coordinates":[[[-111.73527526855469,41.995094299316406],...]]}}
...
```

That example is a good demonstration of the design, because it pipes into jq. The CLI is not a separate tool with its own data model, it is the same library exposed as a command, so the output is GeoJSON and the composition story is shell pipelines rather than a Python session.

The --compact flag produces single-line JSON, which is what makes the output pleasant to pipe, and the fact that the geometry appears as a nested coordinate array rather than a WKT string is the GeoJSON model carried all the way through.

The entry point is registered in pyproject.toml as fio = fiona.fio.main:main_group, and the group naming suggests the CLI has subcommands beyond cat. The Dockerfile in the repository root makes the same command the default entry point, with CMD set to --help.

That Dockerfile is worth reading for another reason, because it is the cleanest statement of the dependency situation in the project. The build stage is based on ghcr.io/osgeo/gdal at the ubuntu-small-3.12.4 tag, with Python 3.14 layered on top along with a compiler and make. The second stage copies the built wheels and installs fiona[test] with --no-index, so the image never reaches a package index at runtime. The entrypoint is the fio command.

## Optional extras, and a maintained but slow release line

The dependency list in pyproject.toml is short for a geospatial library, and the reason is that everything heavy is optional or is GDAL itself.

The required dependencies are attrs at 19.2.0 or newer, certifi, click at about 8.0, cligj at 0.5 or newer, and importlib-metadata for Python below 3.10. The build requirements are setuptools at 67.8 or newer and Cython between 3.1 and 3.3, which is why the topic list includes cython.

The optional extras cover the interesting cases. The calc extra adds pyparsing and shapely, which is what you need for the geometry work the README's example does. The s3 extra adds boto3 at 1.3.1 or newer, for the cloud storage path. The test extra pulls aiohttp, fsspec, pytest and pytest-cov, and it depends on fiona[s3]. The all extra combines them.

The version is read dynamically from fiona.__version__, and the readme is assembled from README.rst, CHANGES.txt and CREDITS.txt, which is why those three files sit at the repository root.

The release cadence is the thing to plan around. The tags are 1.10.1 from 2024-09-16, 1.10.0 from 2024-09-04 and 1.10.0rc1 from 2024-08-22, so the 1.10 line shipped in the autumn of 2024. The last push was on 2026-10-15, so the tree is being worked on, and the classifiers still list Python 3.8 through 3.12 while the README says Fiona 1.10 requires Python 3.8 or higher and GDAL 3.4 or higher.

That gap between the last release and the current tree is worth a look before you pin, because the main branch on a mature geospatial library tends to carry a churn that a patch release does not.

## Conclusion

Fiona suits a Python geospatial workflow that wants readable, streaming feature access without the complexity of the GDAL bindings, since a feature is a data class rather than a Python binding object, and a filter over a bounding box avoids loading the whole dataset. It is the wrong tool for a production deployment that needs optional format drivers such as GML, because the binary wheels omit them and the README is explicit that the wheels are not tested for compatibility with other binary wheels, conda packages or QGIS. Before you deploy, check which drivers your data actually needs, and if it needs more than the wheels carry, install from source with pip install --no-binary fiona fiona or use conda-forge, which the README points at for access to more optional format drivers.

## FAQ

### How do I install Fiona?

Run pip install fiona for the binary wheel. Fiona 1.10 requires Python 3.8 or higher and GDAL 3.4 or higher, and the README notes that many users find Anaconda and conda-forge a good way to install it and get access to more optional format drivers.

### Why does my Fiona install not support the format I need?

The README states that the binary wheels are mainly intended to make installation easy for simple applications, that they omit many of GDAL's optional format drivers, and that if you need something like GML support you will need to build and install Fiona from a source distribution.

### Does Fiona do geometry operations?

No. The features are data classes modelled on the GeoJSON format with no spatial methods of their own, so the README says you need Shapely or something like it if you want to transform them.

### Can Fiona read data directly from a URL?

Yes. The README's example opens a zip+https path, and the library supports zipped and in-memory virtual file systems, so data can be read from files on your hard drive or in cloud storage.

### What is the fio command in Fiona?

It is Fiona's command line interface, registered as the fio entry point, and its fio cat command streams GeoJSON features from any dataset, for example fio cat --compact tests/data/coutwildrnp.shp piped into jq.

## Sources

- [License: BSD-3-Clause](https://github.com/Toblerity/Fiona/blob/main/LICENSE)
- [Project website](https://fiona.readthedocs.io/)
- [README](https://github.com/Toblerity/Fiona/blob/main/README.md)
- [Releases](https://github.com/Toblerity/Fiona/releases)
- [Toblerity/Fiona on GitHub](https://github.com/Toblerity/Fiona)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/toblerity-fiona
