Open-source project
pola-rs/geopolars avatar
pola-rs/geopolars

GeoPolars and the case for geospatial dataframes in Rust and Python

Geospatial extensions for Polars

950 stars36 forksPythonMIT

At a glance

What is it?
GeoPolars extends the Polars dataframe library with geospatial types, using GeoArrow as its internal memory model and GeoRust's geo for algorithms. It is described as a prototype, stores geometries as WKB for now, and was unblocked in November 2025 when Polars added Arrow extension type support.
Who is it for?
GeoPolars fits developers who want Polars-style dataframes over spatial data, need a Rust core they can call from Python, and are willing to work against an alpha API. It does not fit production pipelines today, because the README states it should not be considered production-ready and the Python package is a v0.1.0-alpha.4, and it does not replace GeoPandas, which the README calls an incredible production-ready tool.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

GeoArrow is the memory model, not an export format

GeoPolars extends the Polars dataframe library for use with geospatial data, and the summary lists the properties that matter: it uses GeoArrow as the internal memory model, it is written in Rust, it has bindings to Python, and it is multithreading capable.

The choice of GeoArrow as the internal model is the load-bearing decision. It means a geometry column in a GeoPolars dataframe is meant to be Arrow-native rather than a blob column that gets converted at the edge, which is what makes it possible for a spatial column to live in the same table as ordinary columns, survive the standard Arrow interchange, and be consumed by other GeoArrow-aware tools without a translation step.

The audience is developers who already work with Polars and want the same execution model and the same lazy dataframe API over spatial columns, plus people who want to call spatial algorithms from Rust without leaving the Polars ecosystem. The project is a CNCF-adjacent piece of the Polars world, hosted under the pola-rs organisation, with the package also published under the geopolars organisation on GitHub.

The repository lists Python as its primary language, though the core is Rust. The repository is not archived, the last push was on 2026-10-19, and there are no GitHub releases for the project.

The project spent a year waiting on Polars extension type support

The most informative paragraph in the project's own overview is the update note at the top, and it describes a dependency rather than a feature.

According to that note, GeoPolars had been blocked on Polars supporting Arrow extension types, but as of November 2025 Polars added support for Arrow extension types. The project says it will now move forward, subject to time constraints, and points to an issue thread for more information, where it also says contributor documentation will come later and asks people to comment on the thread for now.

This is worth understanding as a design constraint rather than a project-management detail. The plan is to implement GeoArrow extension types for seamless handling of CRS metadata in Rust, rather than in the Python wrapper. Doing that in Rust rather than in the wrapper matters, because the wrapper is where metadata handling tends to become a per-row Python cost. The blocker was upstream, and the block was on a Polars feature rather than on anything geo-specific, which tells you the project is betting on the Polars data type system rather than working around it.

It also tells you what to expect from the schedule. The README hedges with subject to time constraints, and the fix landed in the upstream project, not here. Anyone planning around GeoPolars is planning around a project that resumes work from a standing start, with the sequencing of its own remaining work decided by a volunteer-run issue thread.

Installing the Python alpha, and what the --pre flag is for

There are two documented ways in, one per language.

From Rust, GeoPolars is published to crates.io under the name geopolars, with API documentation at docs.rs/geopolars.

From Python, an early alpha, version v0.1.0-alpha.4, is published to PyPI and needs the pre-release flag.

bash
pip install --pre geopolars

The --pre flag is not optional for this package as published, because a pre-release version is not selected by default. If you install without it you may not get the alpha at all.

The publishing process includes binary wheels for many platforms, and the README says this should make installation easy without needing to compile the underlying Rust code from source. That is the single most practical fact for a Python user, because a Polars-style library that needs a Rust toolchain to install is a different proposition from one that does not.

A third target is planned rather than available. The project notes that Polars itself does not yet exist in WebAssembly, though there has been discussion about adding bindings for it, and that the long-term goal of GeoPolars is to have a WebAssembly API as well. The repository layout backs that up: the Cargo workspace excludes a wasm-geopolars directory, so the WebAssembly work has a place reserved for it, but it is not in the current build.

Geometries are WKB buffers today, and every operation copies them

The future work section states the two largest pieces of pending work, and both are performance problems with the same root cause.

The first is storing geometries in the efficient Arrow-native format rather than as WKB buffers, which is what the prototype currently does. The notes say this is blocked on Polars, which does not currently support Arrow FixedSizeList data types, and that Polars has recently expressed openness to adding minimal FixedSizeList support.

The second is enabling the georust/geo algorithms to access Arrow data with zero copy. The prototype currently copies WKB geometries into geo structs on each geometry operation, and the README calls that expensive. This one is blocked on adding support to the geo library for geometry access traits, described as a large undertaking, with a discussion thread linked.

So the honest performance picture is: the Arrow-native layout is not there yet, and even where Arrow data is used, spatial algorithms take a copy per operation. For a workload that runs a buffer intersection over a million geometries, that copy is the difference between a query that finishes and a query that does not. The project publishes no benchmark, so there is no number to check your workload against, and the December 2025 note is the most recent signal about direction.

This is the reason to treat the project as a prototype, and the README says so plainly: at this point, GeoPolars is a prototype and should not be considered production-ready.

The comparison with GeoPandas is a statement about the web, not about quality

The project has a section titled Comparison with GeoPandas, and it is worth reading closely because it is unusually candid for a project competing in the same space.

It calls GeoPandas, together with its underlying libraries shapely and GEOS, an incredible production-ready tool, and then says GeoPolars is nowhere near the functionality or stability of GeoPandas. The stated advantage that follows is not about features. It is that, because of the pure-Rust core, GeoPolars will be much easier to use in WebAssembly.

So the difference in approach between the two is a deployment target. GeoPandas builds on a compiled C and C++ geospatial stack, which is why it is what production geospatial Python looks like today, and why it is also hard to ship to a browser. A pure-Rust core is a prerequisite for a WebAssembly build, and the notes are candid that the WebAssembly API is a long-term goal rather than a current feature, with the Polars side of it still not existing in WebAssembly at all.

The practical reading for an evaluator is that GeoPolars and GeoPandas are not substitutes today. One is a production tool with a large feature surface and a slower execution model, the other is a prototype with an execution model borrowed from Polars and a deployment story that does not exist yet. The line the README draws is about where each will be strong, and it is honest about which side of the line GeoPolars is on today.

A pinned Polars revision and two excluded directories

The Cargo.toml is short and every line in it constrains what a user gets.

toml
[workspace]
members = ["geopolars/geopolars-arrow", "geopolars/geopolars-extension"]
exclude = ["py-geopolars", "wasm-geopolars"]
resolver = "2"

The workspace has two members, the Arrow layer and the extension layer, and it excludes the Python binding crate and the WebAssembly crate, so those are built separately.

The dependency on Polars is not a version range. It is a git dependency pinned to an exact revision, with the dtype-extension feature enabled.

toml
polars = { git = "https://github.com/pola-rs/polars", rev = "0c6dca54ae4a33b3f31191748ad6a5ffd5452822", features = [
    "dtype-extension",
] }

That is a deliberate trade. A revision pin means the build is reproducible and the Arrow extension type work lines up with the exact upstream state the author tested against, but it also means the build fetches from a Git repository rather than a registry, and that a Polars change breaking the extension type API is not something the published package absorbs for you. The extension feature is on the Polars side, the Arrow crates are pinned at version 56, and the GeoArrow crates are at 0.6.

The workspace package metadata sets version 0.1.0-alpha.4, matching the Python alpha, edition 2024, rust-version 1.85, the MIT OR Apache-2.0 licence and the science::geo category. The repository's own licence file is MIT. The top level of the repository adds a data directory, a static directory for assets such as the logo, and a .pre-commit-config.yaml, which is a sign the project expects contributions to go through formatted checks.

Editorial conclusion

GeoPolars fits developers who want Polars-style dataframes over spatial data, need a Rust core they can call from Python, and are willing to work against an alpha API. It does not fit production pipelines today, because the README states it should not be considered production-ready and the Python package is a v0.1.0-alpha.4, and it does not replace GeoPandas, which the README calls an incredible production-ready tool. Before adopting it, confirm the pinned Polars revision in Cargo.toml still matches the one your environment runs, read the December 2025 update and the linked issue thread for the current state of the work, and check the known WKB copy cost against the size of your geometries.

Frequently asked questions

How do I install GeoPolars for Python?

Run `pip install --pre geopolars`. The published version is an early alpha, v0.1.0-alpha.4, and the pre-release flag is needed to select it. Binary wheels for many platforms are published, so compiling the Rust core from source is not required.

Is GeoPolars production ready?

The project states that GeoPolars is a prototype and should not be considered production-ready. It also says the project is nowhere near the functionality or stability of GeoPandas.

Why was GeoPolars blocked and what unblocked it?

The project said GeoPolars had been blocked on Polars supporting Arrow extension types, and that as of November 2025 Polars added support for Arrow extension types. The project says it will now move forward, subject to time constraints, and points to an issue thread for more information.

How are geometries stored in GeoPolars right now?

As WKB buffers rather than in the Arrow-native format. Storing geometries is listed in the Arrow-native format as future work blocked on Polars support for Arrow FixedSizeList data types, and notes that spatial operations currently copy WKB geometries into geo structs, which it calls expensive.

Which version of Polars does GeoPolars build against?

Cargo.toml pins Polars as a git dependency at revision 0c6dca54ae4a33b3f31191748ad6a5ffd5452822 with the dtype-extension feature enabled, rather than using a version range.

Official sources

  1. Issues
  2. License: MIT
  3. pola-rs/geopolars on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pola-rs-geopolars.svg)](https://hysenlabs.com/projects/pola-rs-geopolars)

Was this useful?