CHAPTER 18
Coordinate transforms — converting between CRS
EPSG:4326 ↔ 3857 by hand, using proj4js, and the practical situations where you need to transform coordinates.
A coordinate reference system (CRS) defines how coordinates map to a location on Earth. Most data you encounter is in one of two CRS, and converting between them is a daily task.
A coordinate reference system (CRS) defines the relationship between coordinates and locations on Earth. Every dataset has one. If two datasets use different CRS, their coordinates are incomparable — like comparing heights in metres and feet without converting. EPSG codes are the standard shorthand for identifying them.
The two you'll use 95% of the time
| EPSG | Name | Units | Used by |
|---|---|---|---|
4326 | WGS84 geographic | Degrees (lat, lon) | GPS, GeoJSON, most APIs |
3857 | Web Mercator | Metres (x, y) | Google Maps, OSM, Mapbox tiles |
The distinction matters in practice because operations that assume planar geometry — computing buffer distances, calculating area, overlaying rasters — work correctly in metres but give wrong results in degrees. A degree of longitude at the equator is ~111 km; a degree of longitude at 60°N is ~56 km. Treating them as equal without projection introduces systematic distortion.
EPSG:4326 → EPSG:3857 (degrees → metres)
This is the Mercator projection formula you saw in Chapter 4, applied to the Web Mercator sphere:
where m (WGS84 equatorial radius), and φ, λ are in radians.
const R = 6_378_137; // metres
function toWebMercator(lat, lon) {
const x = (lon * Math.PI / 180) * R;
const y = Math.log(Math.tan(Math.PI / 4 + (lat * Math.PI / 180) / 2)) * R;
return { x, y };
}
EPSG:3857 → EPSG:4326 (metres → degrees)
The inverse:
function fromWebMercator(x, y) {
const lon = (x / R) * (180 / Math.PI);
const lat = (2 * Math.atan(Math.exp(y / R)) - Math.PI / 2) * (180 / Math.PI);
return { lat, lon };
}
CRS converter — EPSG:4326 ↔ EPSG:3857
Valid range for Web Mercator
Web Mercator cannot represent the poles. The practical limits are:
- Longitude: −180° to +180°
- Latitude: −85.051129° to +85.051129°
At exactly ±90°, the formula produces ±∞ in the y direction. Google Maps and friends clip to ±85.051129° to produce a square world tile.
Using proj4js
For anything beyond 4326 ↔ 3857, use proj4:
npm install proj4
import proj4 from "proj4";
// Define your custom CRS (find definitions at epsg.io)
proj4.defs("EPSG:32642", "+proj=utm +zone=42 +datum=WGS84 +units=m +no_defs");
// Convert Lahore from WGS84 to UTM Zone 42N
const [easting, northing] = proj4("EPSG:4326", "EPSG:32642", [74.3587, 31.5204]);
// → [381453, 3488694] (metres from zone origin)
Continue reading "Coordinate transforms — converting between CRS"
You've reached the end of the free preview. Unlock all 22 paid chapters, including distance math, bearings, polygons, spatial indexing, and 3D map rendering — plus a downloadable PDF and the companion code repo.
- All 22 paid chapters with worked examples
- Downloadable PDF for offline reading
- Companion GitHub repo (JavaScript + Python)
- Free updates for life
Multiple payment options including Wise, PayPal, and bank transfer.
Related chapters
- Coordinate systems: latitude and longitude — the input lat/lon system
- Map projections — flattening the globe — what you're transforming between
- ECEF and 3D coordinate systems — the 3D Cartesian system at the centre of transforms