Skip to content
transform

Lat/Lon or Lon/Lat? The EPSG:4326 Axis Order Problem, Solved

6 min read

EPSG:4326 officially puts latitude first, but GeoJSON, proj4 and most software put longitude first. This mismatch is the most common coordinate bug in GIS — here is how every major tool handles it.

If your point shows up in the ocean off the coast of West Africa, swims to the wrong hemisphere, or your bounding box has zero area — you have an axis order bug. It is the single most common coordinate mistake in GIS, and it exists because two reasonable conventions collided.

The two conventions

The EPSG registry defines EPSG:4326 with latitude first, longitude second — the convention of geodesy, navigation and everyday speech ("48.8584° N, 2.2945° E").

Almost all GIS software instead uses longitude first, latitude second, treating coordinates as mathematical x/y: x = east-west = longitude, y = north-south = latitude. GeoJSON (RFC 7946) mandates lon/lat. Shapefiles, proj4, PostGIS geometry, Leaflet's L.latLng aside, the entire web-mapping stack thinks in lon/lat.

Both are internally consistent. The bugs happen at the seams — when data crosses from one convention to the other.

How major tools behave

  • GeoJSON: always [longitude, latitude]. No exceptions, by specification.
  • proj4 / proj4js: longitude first, in degrees, for geographic CRSs.
  • pyproj: honours the EPSG axis order by default — Transformer.from_crs("EPSG:4326", ...) expects latitude first! Pass always_xy=True to force lon/lat and match GIS convention.
  • GDAL/OGR (3.x): honours authority order by default; set OAMS_TRADITIONAL_GIS_ORDER on the spatial reference to get classic lon/lat behaviour.
  • PostGIS: ST_MakePoint(lon, lat) — x first. ST_AsLatLonText exists precisely because output often needs the other order.
  • WMS: version 1.1 uses lon/lat for EPSG:4326 bounding boxes; version 1.3 switched to lat/lon. The same request against different versions can flip your BBOX.
  • Leaflet: [lat, lng] in its API — the opposite of GeoJSON, in the same application.

How to never get bitten

  • Decide one internal convention (lon/lat is the pragmatic choice) and convert at the boundaries.
  • In pyproj, write always_xy=True on every transformer. Make it a code-review rule.
  • In GDAL 3+, set the axis mapping strategy explicitly rather than relying on defaults.
  • Sanity-check magnitudes: latitude can never exceed 90. A "latitude" of 139.7 is a longitude.
  • Watch WMS versions in legacy integrations — the 1.1 → 1.3 flip is a classic silent breaker.

The converter on this site accepts both "lon, lat" and DMS input and labels the expected order for every CRS, so you can verify a suspicious coordinate in seconds.

Related coordinate reference systems

Frequently asked questions

Is EPSG:4326 lat/lon or lon/lat?
The EPSG definition is latitude first. Most software (GeoJSON, proj4, PostGIS, shapefiles) nevertheless uses longitude first. You must know which convention each tool in your pipeline assumes.
Why did my points end up in the ocean near Africa?
Swapped axes near (0, 0) — the null island signature. A lon/lat pair read as lat/lon mirrors positions across the equator/prime-meridian axes.
What does always_xy=True do in pyproj?
It forces transformers to accept and return longitude/easting first regardless of the CRS's official axis order — matching the convention of GeoJSON and virtually all GIS software.