GeoJSON and CSV Maps, Explained
After reading this you will know how GeoJSON stores geometry, how a CSV of coordinates becomes a set of pins, why longitude comes before latitude in GeoJSON but latitude usually comes first in a spreadsheet, and how to spot the mistakes that put your data in the ocean off West Africa.
What the viewer does
The tool takes two kinds of input and draws both on the same pannable map. The first is a GeoJSON file, a text format that describes points, lines and polygons using plain coordinate arrays. The second is a CSV with a latitude column and a longitude column, where each row becomes one pin.
Here is the hook. Suppose you have a CSV of three cities:
city,lat,lon,population London,51.5074,-0.1278,8982000 Paris,48.8566,2.3522,2161000 Berlin,52.5200,13.4050,3645000
Drop that in and you get three pins across Western Europe, each one clickable to show its city and population. Color the pins by population and London goes to one end of the scale, Paris to the other. No account, no upload: the file is read in the browser and the parsing happens on your machine.
How GeoJSON stores a shape
GeoJSON is JSON with a fixed vocabulary. Every feature has a geometry and a bag of properties. The geometry names its type and lists coordinates. A single point in London looks like this:
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-0.1278, 51.5074] },
"properties": { "city": "London" }
}
Read the coordinate array carefully. The first number is -0.1278, the longitude. The second is 51.5074, the latitude. GeoJSON always writes longitude first, latitude second, because the format follows the math convention of (x, y) where x runs east and y runs north. This is the single most common source of maps that look scrambled.
Lines and polygons nest the same pairs into deeper arrays. A LineString is a list of positions. A Polygon is a list of rings, and each ring is a closed list of positions where the last pair repeats the first. So the coordinate depth tells you the type: one pair for a point, a list of pairs for a line, a list of lists for a polygon.
If your points land in the Gulf of Guinea near latitude 0, longitude 0, you almost certainly swapped the two numbers or left blank cells that parsed as zero. That spot is called Null Island for exactly this reason.
How a CSV becomes pins
A spreadsheet has no geometry column, so the tool has to guess which columns hold coordinates. It looks at column names first, matching common labels like lat, latitude, lon, lng, longitude, x and y. It also checks value ranges, since latitude must fall in [-90, 90] and longitude in [-180, 180].
Note the ordering flip. In a CSV people usually write latitude first because that is how we say coordinates out loud ("fifty-one point five north, zero point one west"). GeoJSON writes longitude first. The viewer handles the translation, but if you later convert your CSV to GeoJSON and hand it to another program, the exported file will carry the GeoJSON order [\text{lon}, \text{lat}]. Do not re-swap it.
The range check is a useful sanity test you can run by eye. Any latitude with a magnitude above 90 is wrong. Any coordinate that reads like 514074 instead of 51.4074 has lost its decimal point, often after passing through a locale that uses commas for decimals.
Distance on a sphere
Once points are on the map you often want the distance between them. Latitude and longitude are angles, not meters, so you cannot use the flat Pythagorean formula directly. Near the equator one degree of longitude spans about 111 km, but at London's latitude of about 51.5 degrees it spans only about 69 km, because the meridians crowd together toward the poles.
The great-circle distance between two points uses the haversine formula:
Here \varphi_1 and \varphi_2 are the two latitudes in radians, \Delta\varphi is their difference, \Delta\lambda is the longitude difference in radians, and R is the Earth's radius, about 6371 km. The angles must be radians: multiply degrees by \pi / 180 \approx 0.01745.
Worked example with the three cities
London to Paris by haversine
Use London at (51.5074, -0.1278) and Paris at (48.8566, 2.3522), both in degrees.
- Convert to radians. \varphi_1 = 51.5074 \times 0.01745 = 0.8990, \varphi_2 = 48.8566 \times 0.01745 = 0.8527.
- Differences: \Delta\varphi = 0.8527 - 0.8990 = -0.04627, and \Delta\lambda = (2.3522 - (-0.1278)) \times 0.01745 = 0.04328.
- Half-angle sines: \sin^2(\Delta\varphi/2) = \sin^2(-0.02314) = 0.0005353. And \sin^2(\Delta\lambda/2) = \sin^2(0.02164) = 0.0004682.
- Latitude cosines: \cos\varphi_1 = 0.6225, \cos\varphi_2 = 0.6574, product 0.4092.
- Inside the root: 0.0005353 + 0.4092 \times 0.0004682 = 0.0007269. Its square root is 0.02696.
- Distance: 2 \times 6371 \times \arcsin(0.02696) = 2 \times 6371 \times 0.02696 = 343.5 km.
The straight-line air distance between the two city centers is about 344 km, which matches published figures. A flat approximation using degrees would have been off, because it ignores the cosine shrink of longitude.
Coloring points by a value
When you color pins by a numeric column, the viewer maps the column's range onto a color scale. Suppose the values are the three populations: 8.982 million, 2.161 million and 3.645 million. A linear scale places each value by its position between the minimum and maximum:
Here v is a row's value, v_{\min} and v_{\max} are the smallest and largest values, and t runs from 0 to 1. Paris is the minimum, so t = 0. London is the maximum, so t = 1. Berlin sits at (3.645 - 2.161) / (8.982 - 2.161) = 1.484 / 6.821 = 0.2176, just over one fifth of the way up.
That 0.2176 tells you something the raw numbers hide: Berlin is much closer to Paris than to London on this scale, because London is an outlier that stretches the top of the range. One large value compresses everything else into the bottom fifth. If your map looks like every pin is the same pale color with one bright dot, an outlier is stretching your scale.
When to use it, and when not
Reach for this viewer to check a file quickly: confirm that coordinates are in the right hemisphere, that a boundary polygon closes properly, that a CSV geocode ran without swapping columns. It is a verification and inspection step, not a publishing pipeline.
It is not the right tool for heavy cartography or for millions of features. Tens of thousands of points render fine. A hundred-megabyte national boundary file with millions of vertices will be slow to draw and slow to pan, because every vertex has to become a path segment in the browser. Simplify such files first, or sample your points.
It is also not a spatial database. If you want to join, filter or aggregate before mapping, do that in a table tool and export a smaller CSV.
Common mistakes
- Swapped axes
- Latitude first in the array instead of longitude. London's
[51.5074, -0.1278]would plot near the Somali coast. Check that longitudes for European data are small and latitudes are around 40 to 60. - Null Island
- Rows with empty coordinate cells that parse as
0, 0all pile up at the intersection of the equator and prime meridian. Filter out zero-zero rows before mapping. - Lost decimal point
- A value like
515074where a comma-decimal locale ate the separator. Any coordinate with a magnitude above 180 is impossible and signals this. - Unclosed polygon rings
- A polygon's first and last coordinate pair must be identical. Some tools tolerate an open ring, some render a jagged gap.
- Mixed coordinate systems
- GeoJSON assumes WGS84 longitude and latitude in degrees. If your data is in a projected system with meters (for example values in the hundreds of thousands), it will not sit anywhere sensible on a degree-based map.
Related tools
Prepare your data before mapping and post-process it after. Clean and trim columns in the CSV Viewer and Editor, and if your source is a spreadsheet, run it through the Excel to CSV Converter first. To reshape or aggregate rows before you map them, use the Pivot Table Maker or write queries in the SQL Playground. When your points contain names or addresses you would rather not display, mask them with the Data Anonymizer. To move between tabular and nested forms, the CSV and JSON Converter handles the plain conversion, and for non-geographic patterns the Data Visualizer offers 29 chart types.
Frequently asked questions
Why does my GeoJSON show up in the wrong place?
Almost always a swapped axis. GeoJSON coordinate arrays are [longitude, latitude], not [latitude, longitude]. Swap London's pair and it moves from the UK to the Indian Ocean off Somalia.
Does my file get uploaded anywhere?
No. The file is read and drawn in your browser. The only network traffic is the map background tiles and the map engine, and neither carries your data.
Which columns does the CSV mode use for coordinates?
It auto-detects from common names (lat, latitude, lon, lng, longitude, x, y) and from value ranges, since latitude fits [-90, 90] and longitude fits [-180, 180]. You can override the choice if the guess is wrong.
How large a file can I open?
Tens of thousands of points render smoothly. Very large boundary files, in the range of a hundred megabytes with millions of vertices, may be slow because every vertex becomes a drawn path segment. Simplify or sample first.
Can I turn my CSV of points into a GeoJSON file?
Yes. The tool can export CSV points as a GeoJSON file for use elsewhere. The exported coordinates use GeoJSON order, longitude first, so do not swap them again when another program reads the file.