Position History
Get a raw position history timeline for an aircraft by tail number or ICAO24 hex code — without requiring a prior search step. Unlike the flight track endpoint, position history is not bounded to a single flight and can span multiple flights in one window.
Choosing a path: For a single archived flight's gate-to-gate track, use registration → flight search → flight_id → track. For a raw timeline across multiple flights or when you do not know the flight boundaries, use registration → positions directly.
Plan tiers: Historical ADS-B hub.
Requirements
x-api-key on every request (direct subscription). Learn more →Pro, Ultra, or Mega — use the path prefix that matches the window you need.
Learn more →By ICAO24
Request
https://data.skylinkapi.com/v3.1/ultra/history/positions/{icao24}| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
icao24 | string | Yes | - | Aircraft ICAO24 hex (6 characters) |
start | string | No | 24 h ago | Window start — ISO 8601 |
end | string | No | now | Window end — ISO 8601 |
limit | integer | No | 1000 | Max position rows (max 5,000 on ULTRA path) |
Query window cannot exceed 90 days on /ultra/history/....
MEGA path — by [ICAO24](https://en.wikipedia.org/wiki/ICAO_24-bit_address) (`/mega/history/...`)Expand section
https://data.skylinkapi.com/v3.1/mega/history/positions/{icao24}| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
icao24 | string | Yes | - | Aircraft ICAO24 hex |
start | string | No | 24 h ago | Window start — ISO 8601 (max 365 days span on MEGA path) |
end | string | No | now | Window end |
limit | integer | No | 1000 | Max positions (max 10,000 on MEGA path) |
Requires Ultra or Mega plan. Same response shape as ULTRA.
By registration
Same response shape as by ICAO24 but accepts a registration tail number (e.g. N12345, G-XWBA) resolved to ICAO24 server-side. Returns 404 if the registration is not in the aircraft registry.
Request
https://data.skylinkapi.com/v3.1/ultra/history/positions/registration/{registration}| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
registration | string | Yes | - | Aircraft tail number |
start | string | No | 24 h ago | Window start — ISO 8601 |
end | string | No | now | Window end — ISO 8601 |
limit | integer | No | 1000 | Max position rows (max 5,000 on ULTRA path) |
MEGA path — by registration (`/mega/history/...`)Expand section
https://data.skylinkapi.com/v3.1/mega/history/positions/registration/{registration}| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
registration | string | Yes | - | Tail number |
start | string | No | 24 h ago | Window start — ISO 8601 (max 365 days span on MEGA path) |
end | string | No | now | Window end |
limit | integer | No | 1000 | Max positions (max 10,000 on MEGA path) |
Requires Ultra or Mega plan. Same response shape as ULTRA.
Response
{
"icao24": "40621d",
"count": 864,
"positions": [
{
"timestamp": "2026-05-13T03:08:05Z",
"icao24": "40621d",
"latitude": 40.6413,
"longitude": -73.7781,
"altitude_baro": 0,
"ground_speed": 12,
"track": 90,
"vertical_rate": 0,
"callsign": "BAW178",
"is_on_ground": true,
"registration": "G-XWBA",
"aircraft_type": "B77W",
"gps_spoofed": false
}
],
"flights": [
{
"flight_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"callsign": "BAW178",
"flight_number": "BAW178",
"departure_airport_icao": "EGLL",
"departure_airport_iata": "LHR",
"departure_airport_name": "London Heathrow Airport",
"arrival_airport_icao": "KJFK",
"arrival_airport_iata": "JFK",
"arrival_airport_name": "John F Kennedy International Airport",
"takeoff_time": "2026-05-12T19:45:00Z",
"landing_time": "2026-05-13T03:08:00Z",
"flight_start": "2026-05-12T19:42:05Z",
"flight_end": "2026-05-13T03:11:10Z",
"flight_state": "ARCHIVED"
}
]
}| Field | Type | Required | Null? | Description |
|---|---|---|---|---|
icao24 | string | Yes | Never | Queried aircraft hex |
count | integer | Yes | Never | Number of items in positions |
positions | array | Yes | Never | Newest-first position snapshots |
flights | array | Yes | Never | Archived flights overlapping the window |
The registration endpoint adds a top-level registration field echoing the resolved tail number; icao24 is populated after server-side lookup.
Flight window (flights[])
| Field | Type | Required | Null? | Description |
|---|---|---|---|---|
flight_id | string | Yes | Never | UUID for detail/track lookups |
callsign | string | null | No | Yes | Callsign during that flight |
flight_number | string | null | No | Yes | Normalized flight number when resolved |
departure_airport_icao | string | null | No | Yes | Departure airport when resolved |
departure_airport_iata | string | null | No | Yes | Departure airport IATA |
departure_airport_name | string | null | No | Yes | Departure airport name |
arrival_airport_icao | string | null | No | Yes | Arrival airport when resolved |
arrival_airport_iata | string | null | No | Yes | Arrival airport IATA |
arrival_airport_name | string | null | No | Yes | Arrival airport name |
takeoff_time | string | null | No | Yes | Takeoff time for that flight (ISO 8601) |
landing_time | string | null | No | Yes | Landing time for that flight (ISO 8601) |
flight_start | string | Yes | Never | First archived position in that flight window |
flight_end | string | Yes | Never | Last archived position in that flight window |
flight_state | string | null | No | Yes | Archive state (e.g. ARCHIVED) |
Client types
"""Typed models for Historical ADS-B - matches historical-adsb.mdx field tables."""from __future__ import annotationsfrom dataclasses import dataclassfrom typing import Literal@dataclassclass HistoricalFlightSummary: flight_id: str icao24: str | None callsign: str | None flight_number: str | None tail_number: str | None departure_airport_icao: str | None arrival_airport_icao: str | None flight_start: str flight_end: str takeoff_time: str | None landing_time: str | None flight_duration_min: float | None distance_nm: float | None@dataclassclass HistoricalPosition: timestamp: str icao24: str latitude: float longitude: float altitude_baro: float | None ground_speed: float | None track: float | None vertical_rate: float | None is_on_ground: bool@dataclassclass HistoricalFlightWindow: flight_id: str callsign: str | None departure_airport_icao: str | None arrival_airport_icao: str | None takeoff_time: str | None landing_time: str | None flight_start: str flight_end: str flight_state: str | None@dataclassclass AirportTrafficFlight: flight_id: str icao24: str | None callsign: str | None departure_airport_icao: str | None arrival_airport_icao: str | None takeoff_time: str | None landing_time: str | None flight_duration_min: float | None distance_nm: float | None@dataclassclass AirportTrafficResponse: icao: str direction: Literal["dep", "arr", "both"] count: int flights: list[AirportTrafficFlight]Integration
Build a playback track from an aircraft tail number. The example below fetches position history via registration, reverses positions into chronological order for map replay, and handles both the 404 (unknown tail) and 422 (window too wide) error cases. Extend to the /mega/history/... path when a 90-day lookback is insufficient.
import osfrom datetime import datetime, timedelta, timezoneimport requestsBASE = "https://data.skylinkapi.com/v3.1"HEADERS = { "x-api-key": os.getenv("SKYLINK_API_KEY") or os.getenv("SKYLINK_API_KEY", "YOUR_API_KEY")}def fetch_positions(icao24: str, *, tier: str = "ultra", hours: int = 24) -> dict: now = datetime.now(timezone.utc) start = (now - timedelta(hours=hours)).strftime("%Y-%m-%dT%H:%M:%SZ") end = now.strftime("%Y-%m-%dT%H:%M:%SZ") r = requests.get( f"{BASE}/{tier}/history/positions/{icao24.lower()}", headers=HEADERS, params={"start": start, "end": end, "limit": 100}, timeout=(10, 30), ) r.raise_for_status() return r.json()if __name__ == "__main__": import json # Resolve icao24 from a recent archived flight r = requests.get( f"{BASE}/ultra/history/flights", headers=HEADERS, params={"callsign": "BAW178", "limit": 1}, timeout=(10, 25), ) r.raise_for_status() flights = r.json().get("flights") or [] if not flights: print("No flight found") else: icao24 = flights[0]["icao24"] data = fetch_positions(icao24) print(json.dumps({"icao24": data.get("icao24"), "count": data.get("count")}, indent=2))Implementation notes
Registration vs hex. Prefer registration when your users know tail numbers; use icao24 when ingesting raw ADS-B feeds. The registration endpoints return 404 when the tail is unknown.
Important: Position history returns positions newest-first. Reverse chronologically for map replay.
Window sizing. At 5-second sampling, a single flight produces ~700–1,500 position rows. For multi-day requests raise limit (up to 5,000 on ULTRA, 10,000 on MEGA) or narrow the window and merge client-side.
Error responses
Plan-gate 401/403: Historical ADS-B hub. Endpoint-specific:
404 — registration not found
{
"detail": "Registration 'N00000' not found"
}Returned by /history/positions/registration/{registration} when the tail number is absent from the aircraft registry.
422 — window too wide
Returned when start/end span exceeds the path maximum — 90 days on /ultra/history/... or 365 days on /mega/history/...:
{
"detail": "Query window exceeds maximum of 90 days for your plan on /ultra/history/..."
}Your SkyLink licence key, for keys bought direct from skylinkapi.com.
In: header
Path Parameters
Query Parameters
Start datetime ISO 8601. Defaults to 24 h ago.
End datetime ISO 8601. Defaults to now.
Max position rows (default 1000, max 5000)
10001 <= value <= 5000Response Body
application/json
application/json
curl -X GET "https://data.skylinkapi.com/v3.1/ultra/history/positions/a835af"null{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string",
"input": null,
"ctx": {}
}
]
}Your SkyLink licence key, for keys bought direct from skylinkapi.com.
In: header
Path Parameters
Query Parameters
Start datetime ISO 8601. Defaults to 24 h ago.
End datetime ISO 8601. Defaults to now.
Max position rows (default 1000, max 5000)
10001 <= value <= 5000Response Body
application/json
application/json
curl -X GET "https://data.skylinkapi.com/v3.1/ultra/history/positions/registration/N12345"null{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string",
"input": null,
"ctx": {}
}
]
}Your SkyLink licence key, for keys bought direct from skylinkapi.com.
In: header
Path Parameters
Query Parameters
Start datetime ISO 8601. Defaults to 24 h ago.
End datetime ISO 8601. Defaults to now.
Max position rows (default 1000, max 10000)
10001 <= value <= 10000Response Body
application/json
application/json
curl -X GET "https://data.skylinkapi.com/v3.1/mega/history/positions/a835af"null{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string",
"input": null,
"ctx": {}
}
]
}Your SkyLink licence key, for keys bought direct from skylinkapi.com.
In: header
Path Parameters
Query Parameters
Start datetime ISO 8601. Defaults to 24 h ago.
End datetime ISO 8601. Defaults to now.
Max position rows (default 1000, max 10000)
10001 <= value <= 10000Response Body
application/json
application/json
curl -X GET "https://data.skylinkapi.com/v3.1/mega/history/positions/registration/N12345"null{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string",
"input": null,
"ctx": {}
}
]
}