Coordinate Reference Systems: Why Your Map Looks Wrong

tool
geometry
bilingual
An interactive lab with Python, R and MapLibre — upload a GeoJSON, find out what CRS it’s actually in, spot a CRS that doesn’t match its own coordinates, and convert it to a different one.
Published

September 6, 2026

Before a geometry can be invalid, or two features can overlap, a file has to actually be where it says it is. A coordinate reference system (CRS) is what makes a pair of numbers mean a specific place on Earth — and it’s easy to get wrong in a way that neither geometry validity nor topology checks would ever catch, because both of those only look at the shape, never at where it actually sits.

Just want to quickly check a file, without the rest of the reading? Use the standalone tool — same engine, less prose.

1. Upload your file

A .geojson, or a shapefile: either as a single .zip, or as the individual .shp/.dbf/.shx files (and optionally .prj) selected together.

2. Why a CRS problem is different

A geometry can be perfectly valid, and every feature can be perfectly consistent with every other, and the whole file can still land thousands of kilometers from where it should. GeoJSON — and MapLibre, the map library this whole site draws with — assume every coordinate is WGS84 (plain longitude/latitude). Neither reprojects anything on its own: whatever numbers you hand them, that’s where they land.

  • CRS — the coordinate reference system a file declares it’s in, read from its own metadata (a .prj file for a shapefile, a crs object for GeoPandas/sf). Some files declare none at all.
  • Geographic vs. projected — a geographic CRS (WGS84 is the common one) uses degrees, roughly -180..180 longitude and -90..90 latitude. A projected CRS (UTM zones, Web Mercator, national grids) uses linear units — usually meters — and the numbers involved are routinely in the hundreds of thousands or millions.
  • The mismatch — a file can declare one kind of CRS while its actual coordinate values look like the other. That disagreement is the single most common reason a map “looks wrong” before you’ve touched a single geometry.

3. Shared map and detection

4. Same spatial question, two languages

Python and R answer “is this CRS geographic or projected?” with one line each:

Python

gdf.crs.is_geographic

R

sf::st_is_longlat(data)

Both ultimately ask PROJ (the library underneath both PyPROJ and sf’s CRS handling) the same question — but the accessor and the formatted CRS string differ: original_crs.to_string() in Python routinely returns "EPSG:4326", while st_crs(data)$input in R returns whatever string the file’s own CRS definition resolved to, sometimes a full human-readable name instead of an EPSG code. Same underlying CRS, not always the same displayed text — worth knowing before assuming a mismatch between the two cards above means an actual data problem, rather than a formatting one.

5. Convert to a different CRS

Once you know the CRS, changing it is one call — to_crs() in GeoPandas, st_transform() in sf. Reuses exactly the data just diagnosed above (gdf in Python, data in R stay in the session between one cell and the next), no new reading of the file.

Note

Converting to a CRS is only correct when the CRS you’re converting from is right in the first place. If the mismatch check above found a problem, to_crs()/st_transform() would mathematically transform numbers that were never really in the declared CRS to begin with, producing a confident-looking but wrong result — fixing the file’s own CRS label (something only you can determine, from where the data actually came from) has to come first.

6. Where to next

  • Geometry looks fine, dataset doesn’t?Topology errors covers overlaps, gaps, slivers, duplicates and dangles — relationships between features, a different problem from CRS entirely.
  • Not sure where to start? → The GeoSpatial File Inspector gives a five-second summary of a file — feature count, geometry type, CRS, bounds, attributes — before you dig into any one check.
  • Just needed the check? → The standalone CRS Inspector & Converter runs the same detection and lets you convert and download directly.