Distance & Bearing Calculator
Name two places — or a whole trip with stops — by town or as lat, lon, and read the surface distance in km, miles and nautical miles, drawn on a world map, with bearing and midpoint. Live in your browser; nothing is uploaded.
Decimal degrees only. Latitude −90…90, longitude −180…180 (negative = south / west). Spaces optional.
Runs entirely in your browser. No coordinate you type is uploaded or logged — the geodesy maths uses a small committed library and works offline.
Offline later: once you have opened this page with a connection, it reopens and works with none — your browser keeps a copy. Town-name search is the exception: its town list is not saved, so type a latitude and longitude instead. Not saved: the very first Polyatic page you ever open (open it again while online), and any page or link you have never opened.
Estimate only: 850 km/h cruise plus 30 min per leg for taxi, climb and descent. No winds, no time on the ground between legs.
Why two distances? The headline km/mi/nmi figure follows the Earth’s real ellipsoid shape (Vincenty) and is the one to use; the Haversine row treats the Earth as a perfect sphere, which is simpler and up to about 0.3% out.
| Leg | km | mi | nmi |
|---|
What this tool measures
Give it two points on the Earth — each as a latitude, longitude pair in decimal degrees — and it works out the great-circle distance between them: the shortest path over the curved surface of the planet, the route a bird or a long-haul aircraft would fly. It also reports the bearing (the compass direction from the first point to the second) and the midpoint, the coordinate exactly half-way along that shortest path. Everything recomputes the instant you change either point.
Typing a town instead of a coordinate
Each point has a Town or city box beside its coordinate box. The two are not separate calculators: picking a suggestion writes that town's latitude, longitude into the coordinate box next to it and every readout recomputes exactly as if you had typed the numbers yourself. The two boxes are independent — choosing a town for point A never touches point B — and you can mix them freely, naming one end by town and typing the other end's coordinates by hand.
The list is 171,041 places from GeoNames: every populated place of 1,000 people or more, labelled with its region and country so two San Franciscos never look identical. The 29,919 places of 18,000+ people load on your first keystroke; the other 141,122 smaller ones (Skagen, Ebeltoft, Hornbæk) arrive in slices of roughly 100–130 KB compressed, fetched only when that main list has no answer for the name you typed. Accents are optional (malmo finds Malmö, tromso finds Tromsø) and a country or a US state code breaks a tie on a common name — Roskilde Denmark, Roskilde, Denmark and Springfield MA all resolve.
Three limits matter more here than on a one-point tool. First, each town is stored on a 0.01-degree grid — a town centre, not a street address. Half a grid step is 0.005°, which is 556 m of latitude and 556 m × cos(latitude) of longitude, so a single endpoint can be up to about 790 m from the point GeoNames actually recorded at the equator and less towards the poles; across both endpoints the distance you read can be off by roughly 1.5 km in the worst case and usually by a few hundred metres. Over Copenhagen → Oslo (483 km) that is under 0.3%; over two towns 20 km apart it is not. Second, matching is exact, not fuzzy — every word you type must appear in the name — so a misspelling finds nothing rather than confidently finding somewhere else. That is deliberate: a distance for the wrong Springfield looks exactly as plausible as one for the right Springfield, and nothing in the readout would tell you. Third, names in non-Latin scripts are searchable only in their own script; there is no transliteration table.
The town list is a static 714 KiB file (731,472 bytes) served from this same site, and it is fetched on your first keystroke in either town box — never when the page loads, and only once for both boxes. A visitor who only ever types coordinates never downloads it. If it will not load, both town boxes disable themselves and say so in one line, and both coordinate boxes and the four route buttons carry on working exactly as they did before the boxes existed. Nothing you type is sent anywhere either way: the whole list is downloaded and searched on your own device.
Haversine vs ellipsoidal (Vincenty) accuracy
There are two common ways to measure distance across the globe, and they differ because the Earth is not a perfect ball. The haversine formula treats the planet as a sphere of one mean radius (about 6,371 km). It is short, fast and never fails to converge, but because the Earth is flattened at the poles — the equatorial radius is about 21 km larger than the polar radius — haversine can be off by up to roughly 0.3%. The Vincenty inverse formula instead models the Earth as the WGS-84 ellipsoid, the same oblate reference shape your phone's GPS uses, and iterates until it agrees to about 0.5 mm. This tool shows the Vincenty result as the headline distance and the haversine value beside it so you can see the difference for yourself. (Vincenty's one weakness is near-antipodal points — places almost exactly opposite each other on the globe — where the iteration can fail to settle; in that rare case the haversine figure is the reliable one.)
Worked example: London → Paris
Take London at 51.5074, -0.1278 and Paris at 48.8566, 2.3522 (both city-centre reference points). The tool returns:
Notice the two distance methods agree to within 360 metres over 344 km — that is the ~0.1% spread you get at this latitude and range. The Eurostar rail journey between the two cities is about 492 km of track, roughly 43% further than the 344 km straight line, which is a good illustration of why great-circle distance is not travel distance.
Bearings and the compass
A bearing is a direction measured in degrees clockwise from true north: 0° is due north, 90° east, 180° south, 270° west. This tool labels each bearing with the nearest of the 16 traditional compass points (N, NNE, NE, ENE, E, …) so a numeric heading like 148° reads at a glance as SSE. Because the shortest path over a sphere is a great circle rather than a line of constant heading, the compass direction changes as you travel — so the initial bearing (the way you set off) differs from the final bearing (the way you are pointing when you arrive), except along the equator or a pure north–south meridian. Sailors and pilots following a great circle re-check their heading periodically for exactly this reason; a fixed-heading rhumb line is simpler to steer but always a little longer.
The midpoint
The midpoint shown is the half-way point along the great-circle path, not the naive average of the two latitudes and longitudes — those only coincide for points on the same meridian. For London → Paris it lands at 50.1886, 1.1466, near Abbeville in northern France, a little west of the straight line you might sketch on a flat map because the shortest curved path bows slightly toward the nearer pole.
Route map and multi-stop trips
The result pane draws the route on a world map. Press Add a stop to turn A → B into a trip of up to 10 legs (11 places); each stop takes a town name or a coordinate exactly like A and B, and Remove takes it out again. Every leg is measured on its own with Vincenty on the WGS-84 ellipsoid, the Legs table lists each one in km, miles and nautical miles, and the trip total is the plain sum of those legs — so the table always adds up.
Worked example — Copenhagen 55.6761, 12.5683 → Paris 48.8566, 2.3522 → Rome 41.9028, 12.4964:
A flight from Copenhagen straight to Rome is about 1,530 km, so the Paris stop adds roughly 600 km — the kind of detour a multi-leg table makes obvious at a glance.
How the line is drawn. The map is a plain equirectangular projection (longitude and latitude as straight x and y) of Natural Earth's 1:110m coastlines, a public-domain dataset vendored with this page, so the map works offline and costs no request to any map server. On a flat map the shortest path bends: Tokyo → San Francisco (8,293 km) arcs north to about 48° N over the Pacific. That route also crosses the 180° meridian, and a naive drawing joins its two ends with a line straight across Asia, Europe and America; this map splits the path where it meets the edge, so it leaves the right-hand side and re-enters on the left at the same latitude. Near the poles, where one degree of travel can sweep many degrees of longitude, the path is sampled more densely so the curve stays smooth. The ◆ marks the point halfway along the whole trip by distance.
The flight-time line is an estimate, not a timetable. It divides each leg by a constant 850 km/h cruise speed and adds 30 minutes per leg for taxi, climb and descent. It ignores winds — on the North Atlantic the jet stream routinely makes the eastbound flight an hour shorter than the westbound one — and real routes are rarely the exact shortest path, so a scheduled block time can differ from this figure by an hour or more on a long leg. It also adds nothing for time on the ground between legs.
Every stop is written into the page address (#lat,lon~lat,lon~…), so Copy link shares the whole trip and reopening the link restores it; older two-point links still open as A → B. Copy leg table copies tab-separated rows that paste straight into a spreadsheet, and SVG / PNG download the map as you see it, in your current light or dark colours.
Honest limits
New to the maths behind it? Great-Circle Distance Explained is a first-principles guide that works the haversine formula step by step, covers rhumb lines and bearings, and explains the honest spherical-vs-ellipsoid accuracy limit.
This is straight-line great-circle distance, not driving distance. It measures the shortest path over the surface of the Earth as the crow flies; it does not know about roads, railways, shipping lanes, terrain, one-way systems or borders. A real road trip is typically 20–40% longer than the great-circle figure, and far longer where water or mountains force a detour — so use this for as-the-crow-flies estimates, flight-distance sanity checks, radius questions and bearing/heading work, not for turn-by-turn route planning. It also assumes both points are at sea level: it ignores altitude, so it will not add the extra distance of climbing a mountain or the slant range to an aircraft overhead. Coordinates are in the WGS-84 datum (what GPS and web maps use); if your source uses a different local datum the result can shift by tens of metres.
Frequently asked questions
What coordinate format should I enter?
Enter decimal degrees as 'latitude, longitude' — for example 51.5074, -0.1278 for London. Latitude runs from -90 (south pole) to 90 (north pole); longitude from -180 to 180, with negative values west of Greenwich. Spaces are optional and a leading + is fine. Degrees-minutes-seconds are not accepted; convert them to decimal first (degrees + minutes/60 + seconds/3600).
Can I type town names instead of coordinates?
Yes. Each point has a "Town or city" box beside its coordinate box, searching 171,041 places from GeoNames — everywhere with 1,000 people or more, so small towns such as Skagen, Ebeltoft and Bad Tölz are found as well as cities. Pick a suggestion and it writes that town's latitude and longitude into the coordinate box for that point, so the distance and bearing you get are the ones you would get by typing those numbers by hand. The two boxes are independent, so you can name one end by town and type the other end's coordinates. Accents are optional and a country or US state code narrows a common name: "Roskilde Denmark" and "Springfield MA" both resolve. Matching is exact rather than fuzzy, so a misspelling finds nothing instead of quietly finding the wrong town. Town coordinates sit on a 0.01-degree grid — a town centre, not a street address — which can move the distance by up to about 1.5 km across both endpoints.
Are my coordinates uploaded anywhere?
No. Every calculation runs in JavaScript in your browser using a small vendored geodesy library committed alongside this page — there is no server call, and neither a coordinate nor a town name you type is sent anywhere. One file is downloaded, and only if you ask for it: your first keystroke in either "Town or city" box fetches the town list, a static 714 KiB file served from this same site, once for both boxes. That transfer carries nothing about what you typed. You can disconnect from the internet and the calculator keeps working from the coordinate boxes; only the town search needs that file.
Can I add stops and see the route on a map?
Yes. Press "Add a stop" to build a trip of up to 10 legs (11 places). Each leg is measured on its own with Vincenty's ellipsoidal formula, the table lists every leg in km, miles and nautical miles, and the trip total is the plain sum of the legs. The route is drawn on an offline world map made from Natural Earth's public-domain 1:110m coastlines; a leg that crosses the 180° meridian, such as Tokyo to San Francisco, leaves one edge of the map and re-enters at the other instead of drawing a line across the whole world. Every stop is kept in the page address, so a copied link reopens the same trip, and the map downloads as SVG or PNG.
How is the flight time estimated?
It is a rough estimate, not a schedule: each leg's distance divided by a constant cruise speed of 850 km/h, plus 30 minutes per leg for taxi, climb and descent. Real block times differ with winds (an eastbound transatlantic flight is often an hour faster than the westbound one), the aircraft, routing around airspace and airport queues, and it includes no time on the ground between legs. Copenhagen to Paris to Rome (2,135 km over two legs) comes out at about 3 h 31 min.
Use it in your own code
Every leg distance, the haversine comparison, both bearings and the midpoint on
this page come from a published Node module — MIT, zero dependencies. Distances are in
metres; points are { lat, lon } in decimal degrees.
npm i @verifyhash/geo-distanceThree lines — New York JFK to London Heathrow
const geo = require('@verifyhash/geo-distance');
const jfk = { lat: 40.6413, lon: -73.7781 }, lhr = { lat: 51.47, lon: -0.4543 };
console.log(`${(geo.vincentyDistance(jfk, lhr) / 1000).toFixed(2)} km Vincenty, ${(geo.haversineDistance(jfk, lhr) / 1000).toFixed(2)} km haversine, initial bearing ${geo.initialBearing(jfk, lhr).toFixed(1)}°`);
prints
5554.91 km Vincenty, 5540.02 km haversine, initial bearing 51.4°
Same answer as the page: enter those two points above and it shows
5,554.91 km, a 5,540.02 km haversine figure and a 51.4° (NE) initial bearing. The 14.9 km gap is
the Earth's flattening, which the spherical haversine formula ignores.
What the package does not include: the multi-stop trip table, the flight-time estimate, the
world map and the town search. One behaviour to plan for: for nearly antipodal points
vincentyDistance throws an error with code VINCENTY_NO_CONVERGE, so
fall back to haversineDistance there.
@verifyhash/geo-distance on npm · version 0.1.1 · MIT · source in the public verifyhash/libs repository · listed with our other libraries on Polyatic libs.