Skip to main content

CI Status Coverage Status PyPI Version DownloadsDOI

Description

A utility library for converting decimal WGS84 longitude and latitude coordinates into ETRS89 (EPSG:25830) and/or British National Grid (More correctly: OSGB36, or EPSG:27700) Eastings and Northings, and vice versa.

Conversion is handled by the Rust lonlat_bng crate, and is quite fast. Some benchmarks can be found here.

Installation

  • uv add convertbng
  • pip install convertbng

Pre-built wheels are published for every supported platform (see Supported Platforms), so the commands above install a ready-to-use binary and compile nothing.

How the package is built

Coordinate conversion is performed by the Rust lonlat_bng crate. convertbng is a PyO3 extension module that depends on it directly, built with maturin. Each wheel contains a single compiled extension module, and no separate shared library.

Building from the source distribution (sdist)

Installing a wheel is the supported path for the platforms listed below. On any other platform, pip and uv will build the sdist, which requires a Rust toolchain.

Installing for local development

  1. Ensure you have a Rust toolchain installed
  2. run uv sync --dev (this builds the extension)
  3. run uv run pytest

Changes to Cargo.toml, Cargo.lock, or any .rs file will bust the cache, triggering a rebuild when uv commands are run.

Supported Python Versions

convertbng supports all currently supported Python versions.

Binary wheels target the CPython Stable ABI (abi3): a single abi3 wheel per platform covers CPython 3.11 and later.

Supported Platforms

  • Linux (manylinux-compatible) x86_64 and aarch64
  • macOS Darwin x86_64 and arm64
  • Windows 64-bit

Windows Binaries

The extension module used by this package has been built with an MSVC toolchain. You shouldn't need to install any additional runtimes in order for the wheel to work, but please open an issue if you encounter any errors.

Usage

The functions accept either a sequence (such as a list or numpy array) of longitude or easting values and a sequence of latitude or northing values, or a single longitude/easting value and single latitude/northing value. Every function returns a tuple of two float64 NumPy arrays (e.g. Eastings and Northings).

NOTE: Coordinate pairs outside the BNG bounding box, or without OSTN15 coverage will return a result of
nan in both arrays, which cannot be mapped. Since transformed coordinates are guaranteed to be returned in the same order as the input, it is trivial to check for this value. Alternatively, ensure your data fall within the bounding box before transforming them:

Longitude:
East: 1.7800
West: -7.5600
Latitude:
North: 60.8400
South: 49.9600

All functions try to be liberal about what containers they accept: list, tuple, array.array, numpy.ndarray, and pretty much anything that has the __iter__ attribute should work, including generators. Inputs must be one-dimensional and the same length (a ValueError is raised otherwise), and must contain numbers (a TypeError is raised otherwise).

from convertbng.cutil import convert_bng, convert_lonlat

# convert a single value
res = convert_bng(lon, lat)

# convert longitude and latitude to OSGB36 Eastings and Northings using OSTN15 corrections
lons = [lon1, lon2, lon3]
lats = [lat1, lat2, lat3]
res_list = convert_bng(lons, lats)

# convert lists of BNG Eastings and Northings to longitude, latitude
eastings = [easting1, easting2, easting3]
northings = [northing1, northing2, northing3]
res_list_en = convert_lonlat(eastings, northings)

# assumes numpy imported as np
lons_np = np.array(lons)
lats_np = np.array(lats)
eastings_np, northings_np = convert_bng(lons_np, lats_np)

Accuracy

The Rust library produces the following results when round-tripping the 40 OSTN15 test points (only differences are shown)

Test Point Input OSGB36 E (m) Input OSGB36 N (m) Lon diff (°) Lat diff (°) E diff (m) N diff (m)
TP27 319188.434 670947.534 — — — +0.001
TP31 9587.909 899448.996 +6×10⁻⁸ -3×10⁻⁸ +0.003 -0.004
TP32 71713.132 938516.404 +2×10⁻⁸ -1×10⁻⁸ +0.001 -0.002
TP37 180862.461 1029604.114 — — — -0.001
TP38 421300.525 1072147.239 — — — -0.001

But I Have a List of Coordinate Pairs

coords = [[1.0, 2.0], [3.0, 4.0]]
a, b = list(zip(*coords))
# a is (1.0, 3.0)
# b is (2.0, 4.0)

But I have Shapely Geometries

from convertbng.cutil import convert_etrs89_to_ll
from shapely.geometry import LineString
from shapely.ops import transform
from math import isnan
from functools import partial

def transform_protect_nan(f, xs, ys):
    # This function protects Shapely against NaN values in the output of the
    # transform, which would otherwise case a segfault.
    xs_t, ys_t = f(xs, ys)
    assert not any([isnan(x) for x in xs_t]), "Transformed xs contains NaNs"
    assert not any([isnan(y) for y in ys_t]), "Transformed ys contains NaNs"
    return xs_t, ys_t

convert_etrs89_to_lonlat_protect_nan = partial(transform_protect_nan, convert_etrs89_to_ll)

line = LineString([[651307.003, 313255.686], [651307.004, 313255.687]])

new_line = transform(convert_etrs89_to_lonlat_protect_nan, line)

Available Conversions (AKA I Want To…)

  • transform longitudes and latitudes to OSGB36 Eastings and Northings very accurately:
    • use convert_bng()
  • transform OSGB36 Eastings and Northings to longitude and latitude, very accurately:
    • use convert_lonlat()
  • transform longitudes and latitudes to ETRS89 Eastings and Northings, very quickly (without OSTN15 corrections):
    • use convert_to_etrs89()
  • transform ETRS89 Eastings and Northings to ETRS89 longitude and latitude, very quickly (the transformation does not use OSTN15):
    • use convert_etrs89_to_ll()
  • convert ETRS89 Eastings and Northings to their most accurate real-world representation, using the OSTN15 corrections:
    • use convert_etrs89_to_osgb36()

Provided for completeness:

  • transform accurate OSGB36 Eastings and Northings to less-accurate ETRS89 Eastings and Northings:
    • use convert_osgb36_to_etrs89()

Relationship between ETRS89 and WGS84

From the Ordnance Survey Transformations and OSGM02™ User guide, p7. Emphasis mine.

[…] ETRS89 is a precise version of the better known WGS84 reference system optimised for use in Europe; however, for most purposes it can be considered equivalent to WGS84. Specifically, the motion of the European continental plate is not apparent in ETRS89, which allows a fixed relationship to be established between this system and Ordnance Survey mapping coordinate systems. Additional precise versions of WGS84 are currently in use, notably ITRS; these are not equivalent to ETRS89. The difference between ITRS and ETRS89 is in the order of 0.25 m (in 1999), and growing by 0.025 m per year in UK and Ireland. This effect is only relevant in international scientific applications. For all navigation, mapping, GIS, and engineering applications within the tectonically stable parts of Europe (including UK and Ireland), the term ETRS89 should be taken as synonymous with WGS84.

In essence, this means that anywhere you see ETRS89 in this README, you can substitute WGS84.

What CRS Are My Data In

  • if you have latitude and longitude coordinates:
    • They're probably WGS84. Everything's fine!
  • if you got your coordinates from a smartphone or a consumer GPS:
    • They're probably WGS84. Everything's fine!
  • if you have x and y coordinates, or you got your coordinates from Google Maps or Bing Maps and they look something like (-626172.1357121646, 6887893.4928337997), or the phrase "Spherical Mercator" is mentioned anywhere:
    • they're probably in Web Mercator. You must convert them to WGS84 first. Use convert_epsg3857_to_wgs84([x_coordinates], [y_coordinates]) to do so.

Accuracy

convert_bng and convert_lonlat first use the standard seven-step Helmert transform to convert coordinates. This is fast, but not particularly accurate – it can introduce positional error up to approximately 5 metres. For most applications, this is not of particular concern – the input data (especially those originating with smartphone GPS) probably exceed this level of error in any case. In order to adjust for this, the OSTN15 adjustments for the kilometer-grid the ETRS89 point falls in are retrieved, and a linear interpolation to give final, accurate coordinates is carried out. This process happens in reverse for convert_lonlat.

OSTN15

OSTN15 data are used for highly accurate conversions from ETRS89 latitude and longitude, or ETRS89 Eastings and Northings to OSGB36 Eastings and Northings, and vice versa. These data will usually have been recorded using the OS Net GNSS reference station network:

Accuracy of Your Data

Conversion of your coordinates using OSTN15 transformations will be accurate, but if you're using consumer equipment, or got your data off the web, be aware that you're converting coordinates which probably weren't accurately recorded in the first place. That's because accurate surveying is difficult.

Accuracy of the OSTN15 transformation used in this library

  • Round-tripping the 40 OSTN15 test points produces a perfect match at 35 of them; the remaining 5 differ by at most 4mm in Eastings/Northings (see table above). The two test points designed to return no data correctly fail.
  • Longitude/latitude residuals are at most ~6×10⁻⁸° (a few mm at this latitude).

A Note on Ellipsoids

WGS84 and ETRS89 coordinates use the GRS80 ellipsoid, whereas OSGB36 uses the Airy 1830 ellipsoid, which provides a regional best fit for Britain. Positions for coordinates in Great Britain can differ by over 100m as a result. It is thus inadvisable to attempt calculations using mixed ETRS89 and OSGB36 coordinates.

OSTN15

Implementation

The extension module is defined in src/lib.rs. It copies each input into a Rust Vec<f64> (reading NumPy arrays and other float64 buffers directly), releases the GIL, and converts the coordinates in parallel using lonlat_bng's threaded functions. The results are handed to NumPy without a further copy.

Building for local development

You need a Rust toolchain. See Installing for local development above for the steps.

Tests

  • install pytest
  • run pytest

License

Blue Oak Model License

Citing Convertbng

If Convertbng has been significant in your research, and you would like to acknowledge the project in your academic publication, we suggest citing it as follows (example in APA style, 7th edition):

Hügel, S. (2021). Convertbng (Version X.Y.Z) [Computer software]. https://doi.org/10.5281/zenodo.5774931

In Bibtex format:

@software{Hugel_Convertbng_2021,
author = {Hügel, Stephan},
doi = {10.5281/zenodo.5774931},
license = {MIT},
month = {12},
title = {{Convertbng}},
url = {https://github.com/urschrei/convertbng},
version = {X.Y.Z},
year = {2021}
}

Metadata

Release files for convertbng 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for convertbng 2.0.0
File Size Uploaded
convertbng-2.0.0.tar.gz 41.8 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for convertbng 2.0.0
File
convertbng-2.0.0-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
convertbng-2.0.0-cp311-abi3-manylinux_2_28_x86_64.whl CPython 3.11 abi3 Linux glibc 2.28+ x86-64 Details
convertbng-2.0.0-cp311-abi3-manylinux_2_28_aarch64.whl CPython 3.11 abi3 Linux glibc 2.28+ ARM64 Details
convertbng-2.0.0-cp311-abi3-macosx_11_0_x86_64.whl CPython 3.11 abi3 macOS 11.0+ x86-64 Details
convertbng-2.0.0-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details

Total release size: 67.9 MB

Release files / convertbng-2.0.0.tar.gz

Download URL convertbng-2.0.0.tar.gz
Size 41.8 kB
Tags Source
SHA-256 checksum
How to use checksums
0536f4652caa6b7842ff581db751c5da0caa021ad081e7665592aa9de70ac485
BLAKE2b-256 checksum
How to use checksums
9236435c8a6c75420c6dc635a9fed8d7a505776eb408213f02711f4e42e2c94f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / convertbng-2.0.0-cp311-abi3-win_amd64.whl

Download URL convertbng-2.0.0-cp311-abi3-win_amd64.whl
Size 13.4 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
aee1ec2a7dd774077a66e4c3ce11fa9682312d7fe5529d8b2fc2f83f0724b371
BLAKE2b-256 checksum
How to use checksums
cbf9dfa79d6e4d34f049d2f92d63f671a2bcd38dd2d2e68b8cbe79ad7ad21a79
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / convertbng-2.0.0-cp311-abi3-manylinux_2_28_x86_64.whl

Download URL convertbng-2.0.0-cp311-abi3-manylinux_2_28_x86_64.whl
Size 13.6 MB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
677ebe21c1a2bc2d9e70ee21b6bd290b89a146211bcc01d213f7ae05dae622f1
BLAKE2b-256 checksum
How to use checksums
90aa4b98846608cead99c3c31c892ac56e6c50e2b38a9c2f9aea63a8e2cc7f83
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / convertbng-2.0.0-cp311-abi3-manylinux_2_28_aarch64.whl

Download URL convertbng-2.0.0-cp311-abi3-manylinux_2_28_aarch64.whl
Size 13.5 MB
Tags CPython 3.11 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
f1e8dcc6fd1e328958d2a762176f458f775c775f31470356c90d0b637dd854cb
BLAKE2b-256 checksum
How to use checksums
530a148a2a7a187bde948d5c3075eb37e2b4d7c4c00e54ce3443afed7a785868
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / convertbng-2.0.0-cp311-abi3-macosx_11_0_x86_64.whl

Download URL convertbng-2.0.0-cp311-abi3-macosx_11_0_x86_64.whl
Size 13.5 MB
Tags CPython 3.11 abi3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
1c7716cd7f63cbfa679fe80607db6cbf6a911f2e3fe46f5fa4b9cf21e7d0531f
BLAKE2b-256 checksum
How to use checksums
2374119b1316993c0f1c0324cad45e41932e620f89045a7b99a45125fee9e482
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / convertbng-2.0.0-cp311-abi3-macosx_11_0_arm64.whl

Download URL convertbng-2.0.0-cp311-abi3-macosx_11_0_arm64.whl
Size 13.8 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ea31e23132e3d8fedd2b7ddf88240a4f062fd0f2f806c10ca317f3b8ab91387b
BLAKE2b-256 checksum
How to use checksums
14f0e9ae88b45c73ba63e68ddcaeab469a5c28ce0a0281c8a578adba5133fbd9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.0 This release

6 release files

0.7.9

21 release files

0.7.8

21 release files

0.7.7

21 release files

0.7.6

21 release files

0.7.5

26 release files

0.7.4

24 release files

0.6.35

8 release files

0.6.33

4 release files

0.6.32

4 release files

0.6.25

8 release files

0.6.15

8 release files

0.6.9

16 release files

0.6.6

15 release files

0.6.4

13 release files

0.6.1

13 release files

0.5.7

7 release files

0.5.5

7 release files

0.5.0

7 release files

0.4.38

7 release files

0.4.35

7 release files

0.4.33

6 release files

0.4.30

5 release files

0.4.28

4 release files

0.4.27

4 release files

0.4.26

3 release files

0.4.25

3 release files

0.4.24

3 release files

0.4.23

3 release files

0.4.22

3 release files

0.4.21

0.4.18

2 release files

0.4.9

1 release file

0.4.8

1 release file

0.4.7

2 release files

0.4.4

3 release files

0.4.3

1 release file

0.4.2

1 release file

0.4.1

2 release files

0.4.0

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.1.25

2 release files

0.1.24

2 release files

0.1.23

2 release files

0.1.22

2 release files

0.1.21

2 release files

0.1.20

2 release files

0.1.18

2 release files

0.1.13

2 release files

0.1.12

2 release files

0.1.11

2 release files

0.1.10

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page