Amtraker (Amtrak) API
Free unofficial Amtrak API with no key: live train positions, delays, consists and every station with coordinates and scheduled services. Tested example and live response.
Endpoint tested and returned HTTP 200 on 2026-08-21
What is the Amtraker (Amtrak) API?
Amtraker is a free, key-free API for Amtrak data. It serves live train positions with delay information and per-stop timings, plus a complete station directory giving coordinates, timezone, street address and the trains scheduled to call at each one.
Amtrak publishes no public developer API, so everything in the American passenger rail ecosystem is reverse-engineered from the map on its own website. Amtraker does that work and re-exposes it as clean, documented JSON — which is why it has become the de facto source for hobbyist trackers, station displays and delay-analysis projects.
The station response is keyed by station code rather than being an array, so `stations.ABQ` addresses Albuquerque directly with no scanning. Each record carries a `trains` array listing the services that call there, using train identifiers in the form `3-19` — route number and departure day — which is how Amtrak distinguishes several instances of the same long-distance service running simultaneously over a multi-day journey. The `tz` field matters more here than in most countries: the Southwest Chief crosses four time zones, and comparing raw timestamps without it produces nonsense.
Quick facts
- Base URL
https://api-v3.amtraker.com/v3- Authentication
- No API key or account. Unofficial community project; not affiliated with or endorsed by Amtrak.
- Rate limit
- No published quota. Positions refresh on Amtrak's own cadence of a few minutes, so polling faster gains nothing.
- Pricing
- Free and open source.
- CORS
- Enabled — callable directly from browser JavaScript
- Official docs
- Read the docs
How to use the Amtraker (Amtrak) API
Every request below was executed against the live API on 2026-08-21, and the response shown is the real body it returned — not an illustration.
1. Fetch every Amtrak station with coordinates and services
GET https://api-v3.amtraker.com/v3/stations
curl 'https://api-v3.amtraker.com/v3/stations'const res = await fetch("https://api-v3.amtraker.com/v3/stations");
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://api-v3.amtraker.com/v3/stations", timeout=20)
res.raise_for_status()
print(res.json()){
"ABE": {
"name": "Aberdeen",
"code": "ABE",
"tz": "America/New_York",
"lat": 39.50844700040231,
"lon": -76.1632600000959,
"hasAddress": true,
"address1": "18 East Bel Air Avenue",
"address2": "",
"city": "Aberdeen",
"state": "MD",
"zip": "21001-3701",
"trains": []
},
"ABN": {
"name": "Absecon",
"code": "ABN",
"tz": "America/New_York",
"lat": 39.424040999819525,
"lon": -74.50147500012103,
"hasAddress": true,
"address1": "Shore Road and Ohio Avenue",
"address2": "",
"city": "Absecon",
"state": "NJ",
"zip": "08201",
"trains": []
},
"ABQ": {
"name": "Albuquerque",
"code": "ABQ",
"tz": "America/Denver",
"lat": 35.082061000451944,
"lon": -106.64797500045553,
"hasAddress": true,
"address1": "320 1st Street SW",
"address2": "",
"city": "Albuquerque",
"state": "NM",
"zip": "87102-3405",
"trains": [
"3-19",
"3-20",
"4-19",
"4-20"
]
},
"ACA": {
"name": "Antioch-Pittsburg",
"code": "ACA",
"tz": "America/Los_Angeles",
"lat": 38.017699999685725,
"lon": -121.81602400045233,
"hasAddress": true,
"address1": "100 I Street",
"address2": "",
"city": "Antioch",
"state": "CA",
"zip": "94509-1122",
"trains": [
"718-20"
]
},
"ACD": {
"name": "Arcadia Valley",
"code": "ACD",
"tz": "America/Chicago",
"lat": 37.592161000273954,
"lon": -90.62440299987063,
"hasAddress": true,
"address1": "13700 Highway 21",
"address2": "",Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
(stations) | path | Optional | `/stations` returns every station keyed by its three-letter code. stations |
(one station) | path | Optional | `/stations/{code}` returns a single station. ABQ |
(trains) | path | Optional | `/trains` returns every train currently running, with positions and stop timings. trains |
(one train) | path | Optional | `/trains/{number}` filters to one route number, which may return several active instances. 3 |
Response fields
(object keys)string- Three-letter Amtrak station codes — ABE, ABN, ABQ. The response is an object, not an array.
name / codestring- Station name and its code.
tzstring- IANA timezone for the station. Essential on routes that cross zones, which most long-distance services do.
lat / lonfloat- Station coordinates as plain numbers.
hasAddress / address1 / city / state / zipboolean / string- Street address where one exists. Some rural stops are platforms with no address at all.
trainsarray- Train identifiers scheduled to call here, in `route-day` form such as "3-19".
(trains endpoint) trainNum, routeName, velocity, headingmixed- On `/trains`: the service number, route name, speed and direction of travel.
(trains endpoint) stations[].schDep / arr, postCmntstring- Scheduled and actual times per stop, plus Amtrak's own delay comment such as "12 minutes late".
What you can build with the Amtraker (Amtrak) API
- Build a live Amtrak train map
- Show a departure board for a specific station
- Alert a passenger when their train is running late
- Analyse on-time performance across a route over time
- Plot the full station network with accurate coordinates
Common errors and how to fix them
Iterating the stations response yields nothing
It is an object keyed by station code, not an array.
Fix: Use `Object.values()` or the equivalent. This shape is convenient for lookup and surprising if you expected a list.
Times compare incorrectly across a route
Stations sit in different time zones and the `tz` field is per-station.
Fix: Convert every timestamp to UTC before comparing. The Southwest Chief alone spans four zones.
A train identifier has a suffix
Identifiers are `route-day`, so one route number has several concurrent instances on multi-day services.
Fix: Match on the full identifier. Filtering on the route number alone conflates trains that departed on different days.
Data goes stale or the API is briefly unavailable
It depends on Amtrak's own undocumented endpoints, which change without notice.
Fix: Fail gracefully and cache the last good response. This is an unofficial source and it will occasionally break when Amtrak changes something.
Amtraker (Amtrak) API — frequently asked questions
Is the Amtrak API free?
Yes. Amtraker is a free, open-source community project with no key or account. It is not affiliated with Amtrak, which publishes no public developer API of its own.
Can I get live train positions?
Yes, from `/trains`, which returns every service currently running with position, speed, heading and per-stop scheduled and actual times, including Amtrak's own delay comments.
Why do train identifiers look like 3-19?
The first part is the route number and the second is the day of the month the service departed. Long-distance trains take more than a day end to end, so several instances of the same route are en route simultaneously and need distinguishing.
How reliable is it?
It is a reverse-engineered wrapper around Amtrak's internal endpoints, so it can break when Amtrak changes them. Cache the last good response and degrade gracefully rather than assuming continuous availability.
Tools that pair with this API
Time Zone Converter
Convert any date and time between world time zones. See UTC offsets, daylight saving handled automatically, and compare multiple zones at once.
Timestamp Converter
Convert timestamps to human-readable dates and dates back to timestamps. Auto-detects seconds vs milliseconds, shows local, UTC and ISO 8601 formats.
Distance Calculator
Calculate the straight-line distance and bearing between two points on a map by latitude/longitude using the Haversine formula — km, miles and nautical miles.
Amtraker (Amtrak) is an independent third-party service and is not affiliated with ByteTools or ByteVancer. Details on this page were verified on 2026-08-21; always check the official documentation before relying on this API in production, as terms and limits can change.