Skip to main content

Great-Circle Geodesy API

REAL DATA

Great-circle distance, bearings, destinations and bounding boxes for WGS 84 coordinates on an explicitly documented mean-Earth sphere.

Authoritative reference data or standards computation

Base URL
/api/geodesy
Capabilities
3 routes
Last updated
July 30, 2026
Data source

GET /api/geodesy/distance

Live requestRuns against the public API
No key required
GET/api/geodesy/distance?lat1=51.5074&lon1=-0.1278&lat2=40.7128&lon2=-74.0060

Request parameters

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/geodesy/distance?lat1=51.5074&lon1=-0.1278&lat2=40.7128&lon2=-74.0060"
const res = await fetch("https://randomapi.dev/api/geodesy/distance?lat1=51.5074&lon1=-0.1278&lat2=40.7128&lon2=-74.0060");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/geodesy/distance?lat1=51.5074&lon1=-0.1278&lat2=40.7128&lon2=-74.0060").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/geodesy/distance?lat1=51.5074&lon1=-0.1278&lat2=40.7128&lon2=-74.0060"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 4
lat1 float required

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

allowed: -90 – 90
example: lat1=51.5074
lon1 float required

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

allowed: -180 – 180
example: lon1=-0.1278
lat2 float required

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

allowed: -90 – 90
example: lat2=40.7128
lon2 float required

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

allowed: -180 – 180
example: lon2=-74.006
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=from,to
exclude list

Return all fields except these (comma-separated).

example: exclude=radiusMeters
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 11
from object

Canonical first coordinate as latitude/longitude.

example: {"latitude":51.5074,"longitude":-0.1278}

to object

Canonical second coordinate as latitude/longitude.

example: {"latitude":40.7128,"longitude":-74.006}

centralAngleDegrees float

Great-circle central angle in degrees.

example: 50.094212

distanceMeters float

Great-circle arc length on the exposed spherical model, in meters.

example: 5570229.874

distanceKilometers float

The same arc length in kilometers.

example: 5570.229874

initialBearingDegrees float nullable

Forward bearing at the first point, clockwise from true north; null for non-unique geometry or a polar first point.

example: 288.33

finalBearingDegrees float nullable

Forward bearing on arrival, clockwise from true north; null for non-unique geometry or a polar destination.

example: 231.21

isCoincident boolean

True when both inputs identify the same point on the sphere.

example: false

isAntipodal boolean

True for diametrically opposite points, where infinitely many great circles connect them.

example: false

model string

Explicit calculation model: mean-earth-sphere (not an ellipsoidal or road distance).

example: mean-earth-sphere

radiusMeters float

IUGG mean Earth radius used by every calculation, in meters.

example: 6371008.8

Documented examples

Build-generated requests and complete responses
3
London to New York
GET /api/geodesy/distance?lat1=51.5074&lon1=-0.1278&lat2=40.7128&lon2=-74.0060
{
  "data": {
    "from": {
      "latitude": 51.5074,
      "longitude": -0.1278
    },
    "to": {
      "latitude": 40.7128,
      "longitude": -74.006
    },
    "centralAngleDegrees": 50.09421156,
    "distanceMeters": 5570229.874,
    "distanceKilometers": 5570.229874,
    "initialBearingDegrees": 288.329701594,
    "finalBearingDegrees": 231.212616824,
    "isCoincident": false,
    "isAntipodal": false,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/distance",
    "params": {
      "lat1": 51.5074,
      "lon1": -0.1278,
      "lat2": 40.7128,
      "lon2": -74.006
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Copenhagen to Tokyo
GET /api/geodesy/distance?lat1=55.6761&lon1=12.5683&lat2=35.6762&lon2=139.6503
{
  "data": {
    "from": {
      "latitude": 55.6761,
      "longitude": 12.5683
    },
    "to": {
      "latitude": 35.6762,
      "longitude": 139.6503
    },
    "centralAngleDegrees": 78.143341114,
    "distanceMeters": 8689155.085,
    "distanceKilometers": 8689.155085,
    "initialBearingDegrees": 41.466326635,
    "finalBearingDegrees": 152.635624504,
    "isCoincident": false,
    "isAntipodal": false,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/distance",
    "params": {
      "lat1": 55.6761,
      "lon1": 12.5683,
      "lat2": 35.6762,
      "lon2": 139.6503
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Antipodal edge case
GET /api/geodesy/distance?lat1=0&lon1=0&lat2=0&lon2=180
{
  "data": {
    "from": {
      "latitude": 0,
      "longitude": 0
    },
    "to": {
      "latitude": 0,
      "longitude": -180
    },
    "centralAngleDegrees": 180,
    "distanceMeters": 20015114.442,
    "distanceKilometers": 20015.114442,
    "initialBearingDegrees": null,
    "finalBearingDegrees": null,
    "isCoincident": false,
    "isAntipodal": true,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/distance",
    "params": {
      "lat1": 0,
      "lon1": 0,
      "lat2": 0,
      "lon2": -180
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}

GET /api/geodesy/destination

Uses the exposed sphere and normalizes longitude. Non-zero journeys from an exact pole are rejected because initial compass bearing is undefined there.

Live requestRuns against the public API
No key required
GET/api/geodesy/destination?lat=55.6761&lon=12.5683&bearing=90&distanceKm=1000

Request parameters

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

Initial bearing clockwise from true north, 0–360 degrees; 360 canonicalizes to 0.

Non-negative great-circle arc distance in kilometers, capped at 40031 (about one mean-Earth circumference).

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/geodesy/destination?lat=55.6761&lon=12.5683&bearing=90&distanceKm=1000"
const res = await fetch("https://randomapi.dev/api/geodesy/destination?lat=55.6761&lon=12.5683&bearing=90&distanceKm=1000");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/geodesy/destination?lat=55.6761&lon=12.5683&bearing=90&distanceKm=1000").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/geodesy/destination?lat=55.6761&lon=12.5683&bearing=90&distanceKm=1000"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 4
lat float required

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

allowed: -90 – 90
example: lat=55.6761
lon float required

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

allowed: -180 – 180
example: lon=12.5683
bearing float required

Initial bearing clockwise from true north, 0–360 degrees; 360 canonicalizes to 0.

allowed: 0 – 360
example: bearing=90
distanceKm float required

Non-negative great-circle arc distance in kilometers, capped at 40031 (about one mean-Earth circumference).

allowed: 0 – 40031
example: distanceKm=1000
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=origin,bearingDegrees
exclude list

Return all fields except these (comma-separated).

example: exclude=radiusMeters
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 7
origin object

Canonical start coordinate.

example: {"latitude":55.6761,"longitude":12.5683}

bearingDegrees float

Canonical initial bearing in [0, 360).

example: 90

distanceKilometers float

Requested spherical arc distance in kilometers.

example: 1000

destination object

Calculated coordinate with longitude normalized to [-180, 180).

example: {"latitude":55.002,"longitude":28.227}

finalBearingDegrees float nullable

Forward bearing at the destination; null for zero distance or a polar destination where local north is undefined.

example: 102.8

model string

Explicit calculation model: mean-earth-sphere (not an ellipsoidal or road distance).

example: mean-earth-sphere

radiusMeters float

IUGG mean Earth radius used by every calculation, in meters.

example: 6371008.8

Documented examples

Build-generated requests and complete responses
3
One thousand kilometers east of Copenhagen
GET /api/geodesy/destination?lat=55.6761&lon=12.5683&bearing=90&distanceKm=1000
{
  "data": {
    "origin": {
      "latitude": 55.6761,
      "longitude": 12.5683
    },
    "bearingDegrees": 90,
    "distanceKilometers": 1000,
    "destination": {
      "latitude": 54.657697998,
      "longitude": 28.246258981
    },
    "finalBearingDegrees": 102.895471621,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/destination",
    "params": {
      "lat": 55.6761,
      "lon": 12.5683,
      "bearing": 90,
      "distanceKm": 1000
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Cross the antimeridian
GET /api/geodesy/destination?lat=0&lon=179&bearing=90&distanceKm=500
{
  "data": {
    "origin": {
      "latitude": 0,
      "longitude": 179
    },
    "bearingDegrees": 90,
    "distanceKilometers": 500,
    "destination": {
      "latitude": 0,
      "longitude": -176.503398181
    },
    "finalBearingDegrees": 90,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/destination",
    "params": {
      "lat": 0,
      "lon": 179,
      "bearing": 90,
      "distanceKm": 500
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Zero-distance identity
GET /api/geodesy/destination?lat=-33.8688&lon=151.2093&bearing=42&distanceKm=0
{
  "data": {
    "origin": {
      "latitude": -33.8688,
      "longitude": 151.2093
    },
    "bearingDegrees": 42,
    "distanceKilometers": 0,
    "destination": {
      "latitude": -33.8688,
      "longitude": 151.2093
    },
    "finalBearingDegrees": null,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/destination",
    "params": {
      "lat": -33.8688,
      "lon": 151.2093,
      "bearing": 42,
      "distanceKm": 0
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}

GET /api/geodesy/bbox

Live requestRuns against the public API
No key required
GET/api/geodesy/bbox?lat=55.6761&lon=12.5683&radiusKm=100

Request parameters

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

Spherical radius in kilometers, 0–40031. A radius reaching either pole spans all longitudes.

Advanced response options4 options

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

Return all fields except these (comma-separated).

Pretty-print the JSON response.

Drop the envelope: return the raw array/object without data/meta wrapper.

Response

Example parameters are ready. Send the request to inspect the live response.

Route reference

Code samples Ready-to-copy requests in 4 languages
Choose a code sample language
curl "https://randomapi.dev/api/geodesy/bbox?lat=55.6761&lon=12.5683&radiusKm=100"
const res = await fetch("https://randomapi.dev/api/geodesy/bbox?lat=55.6761&lon=12.5683&radiusKm=100");
const { data, meta } = await res.json();
import requests

data = requests.get("https://randomapi.dev/api/geodesy/bbox?lat=55.6761&lon=12.5683&radiusKm=100").json()["data"]
$json = json_decode(file_get_contents(
  "https://randomapi.dev/api/geodesy/bbox?lat=55.6761&lon=12.5683&radiusKm=100"
), true);
$data = $json["data"];
Parameters Route-specific request inputs 3
lat float required

Latitude in WGS 84 decimal degrees, from -90 to 90 inclusive.

allowed: -90 – 90
example: lat=55.6761
lon float required

Longitude in WGS 84 decimal degrees, from -180 to 180 inclusive; +180 canonicalizes to -180.

allowed: -180 – 180
example: lon=12.5683
radiusKm float required

Spherical radius in kilometers, 0–40031. A radius reaching either pole spans all longitudes.

allowed: 0 – 40031
example: radiusKm=100
Universal parameters Shared response and formatting options 4
fields list

Return only these fields (comma-separated). Mutually exclusive with 'exclude'.

example: fields=center,radiusKilometers
exclude list

Return all fields except these (comma-separated).

example: exclude=radiusMeters
pretty boolean

Pretty-print the JSON response.

default: false
example: pretty=true
unwrap boolean

Drop the envelope: return the raw array/object without data/meta wrapper.

default: false
example: unwrap=true
Response schema Fields returned in each record 10
center object

Canonical center coordinate.

example: {"latitude":55.6761,"longitude":12.5683}

radiusKilometers float

Requested spherical radius in kilometers.

example: 100

south float

Minimum latitude, clamped to -90.

example: 54.7768

north float

Maximum latitude, clamped to 90.

example: 56.5754

west float

Western longitude; greater than east when the box crosses the antimeridian.

example: 10.98

east float

Eastern longitude; less than west when the box crosses the antimeridian.

example: 14.15

crossesAntimeridian boolean

True when the longitude interval wraps across ±180 degrees.

example: false

spansAllLongitudes boolean

True when the radius reaches a pole or covers the full globe.

example: false

model string

Explicit calculation model: mean-earth-sphere (not an ellipsoidal or road distance).

example: mean-earth-sphere

radiusMeters float

IUGG mean Earth radius used by every calculation, in meters.

example: 6371008.8

Documented examples

Build-generated requests and complete responses
3
One-hundred-kilometer Copenhagen box
GET /api/geodesy/bbox?lat=55.6761&lon=12.5683&radiusKm=100
{
  "data": {
    "center": {
      "latitude": 55.6761,
      "longitude": 12.5683
    },
    "radiusKilometers": 100,
    "south": 54.776779636,
    "north": 56.575420364,
    "west": 10.973253875,
    "east": 14.163346125,
    "crossesAntimeridian": false,
    "spansAllLongitudes": false,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/bbox",
    "params": {
      "lat": 55.6761,
      "lon": 12.5683,
      "radiusKm": 100
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
Antimeridian-crossing box
GET /api/geodesy/bbox?lat=0&lon=179&radiusKm=500
{
  "data": {
    "center": {
      "latitude": 0,
      "longitude": 179
    },
    "radiusKilometers": 500,
    "south": -4.496601819,
    "north": 4.496601819,
    "west": 174.503398181,
    "east": -176.503398181,
    "crossesAntimeridian": true,
    "spansAllLongitudes": false,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/bbox",
    "params": {
      "lat": 0,
      "lon": 179,
      "radiusKm": 500
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}
North-pole-reaching box
GET /api/geodesy/bbox?lat=89&lon=30&radiusKm=500
{
  "data": {
    "center": {
      "latitude": 89,
      "longitude": 30
    },
    "radiusKilometers": 500,
    "south": 84.503398181,
    "north": 90,
    "west": -180,
    "east": 180,
    "crossesAntimeridian": false,
    "spansAllLongitudes": true,
    "model": "mean-earth-sphere",
    "radiusMeters": 6371008.8
  },
  "meta": {
    "endpoint": "geodesy",
    "route": "/bbox",
    "params": {
      "lat": 89,
      "lon": 30,
      "radiusKm": 500
    },
    "generatedAt": "2026-07-30T15:14:08.000Z"
  }
}

About this API

Coverage & behavior

Pure spherical geodesy for coordinate work: great-circle distance and bearings, a destination from bearing plus distance, and a radius bounding box. Inputs use WGS 84 latitude/longitude order and ranges, while the calculation surface is an explicitly documented sphere with the IUGG mean Earth radius 6,371,008.8 metres.

This honesty matters: the endpoint does not claim ellipsoidal survey precision, road distance, flight routing, terrain clearance or uncertainty inferred from decimal digits. The response always includes model: "mean-earth-sphere" and radiusMeters, so callers can decide whether the approximation fits their use case.

  • /distance returns central angle, distance, initial/final bearings, and explicit coincident/antipodal flags. Bearings are null where a unique direction or local north reference does not exist (coincident/antipodal geometry and the relevant geographic pole).
  • /destination follows the great circle from one point for a bearing and non-negative distance, normalizing the result longitude to [-180, 180). A non-zero journey cannot start exactly at a pole because an initial compass bearing has no local-north reference there; that case is an explicit 400.
  • /bbox returns the smallest latitude/longitude-aligned spherical bounding box for a radius. It exposes antimeridian crossing (west > east) and pole/full-longitude coverage instead of returning a misleading ordinary box.

All calculations are deterministic, synchronous and dataset-free.

Use it for

  • Estimate great-circle separation and bearings between map markers without a client geospatial library
  • Compute a destination point for location demos, proximity fixtures and map-camera tests
  • Build a coarse pre-filter bounding box before a precise distance check, including dateline and pole cases

Frequently asked questions

Is the distance an exact WGS 84 ellipsoid distance?

No. Coordinates use WGS 84 ranges, but the calculation uses the exposed IUGG mean-Earth sphere. It is a great-circle approximation, not survey, route or terrain distance.

What happens at coincident or antipodal points?

Distance remains defined, but coincident/antipodal bearings are null. A bearing evaluated at a pole is also null; a non-zero destination journey cannot start at a pole and returns 400.

Can bounding boxes cross the international date line?

Yes. crossesAntimeridian is true and west is greater than east; boxes reaching a pole instead set spansAllLongitudes and use -180 to 180.

Standards & references