TSA wait time data and free API

Security Wait Times publishes its wait figures as free JSON. There is no key and no sign-up. 3 endpoints cover the current waits at 440 US airports, the airport list, and the model parameters behind every estimate.

Right now the endpoint returns 440 airports: 6 live, 434 modeled (94 on the primary model, 340 on the simplified one) and 0 unavailable. Live feeds that also carry a PreCheck figure: EWR, JFK, LGA, PDX.

Live, modeled and unavailable

Every airport record carries a measurement field with one of 3 values.

  • live: the current standard-lane figure comes from the airport operator feed. 6 airports have one: DTW, EWR, JFK, LGA, PDX and PHX. We read the feeds about every 5 minutes.
  • modeled: the figure comes from our time-of-day model. The primary model covers 100 airports, including the 6 live ones, and has a weekday effect. The other 340 airports use a simplified version of the same daily shape without one.
  • unavailable: the airport has a page on the site but no model entry, so the minutes fields are null. No airport is in this state today, but clients should handle it.

PreCheck has its own field, precheck_measurement. It reads live only while a live feed also publishes a PreCheck figure, and modelled everywhere else. The response names the airports where that is true in notes.precheck_measurement.

A live figure is a reading of the current wait. A modeled figure is what the model expects for that airport at this hour. Neither is a promise, and TSA does not guarantee expedited screening.

1. Current waits

GET https://securitywaittimes.com/wp-json/swt/v1/waitGET https://securitywaittimes.com/wp-json/swt/v1/wait?iata=ATL

Parameter: iata, optional. A 3-letter airport code, upper or lower case. Characters other than letters are removed before the lookup. Leave it out to get all 440 airports.

One airport returns an object with airport, notes and generated_at. All airports returns count, live_count, modelled_count, unavailable_count, airports (sorted by code), notes and generated_at.

Airport fields:

  • iata: the code the airport page uses. DJT keeps its page code even though the airport now calls itself DJT.
  • name, city, state: text.
  • standard_minutes, precheck_minutes: whole minutes, or null when unavailable.
  • measurement, precheck_measurement: live, modelled or unavailable.
  • model: primary, simplified, or null when unavailable.
  • source: a short description of where the figure came from.
  • updated_at: when the figure was last refreshed, UTC, as YYYY-MM-DD HH:MM:SS. For simplified-model airports it is the time of your request, because the figure is computed then.
  • busiest_hour, quietest_hour: the busiest and quietest hour in the model between 5 a.m. and 11 p.m. local time (for example 6 a.m. to 7 a.m.).
  • url: the airport page.

Unknown code: HTTP 404 with {"code":"swt_not_found","message":"Unknown airport code.","data":{"status":404}}.

Example, trimmed. Values change.

GET /wp-json/swt/v1/wait?iata=EWR

{
  "airport": {
    "iata": "EWR",
    "name": "Newark Liberty International Airport",
    "city": "Newark",
    "state": "NJ",
    "standard_minutes": 46,
    "precheck_minutes": 13,
    "measurement": "live",
    "precheck_measurement": "live",
    "model": "primary",
    "source": "Live checkpoint feed (Port Authority of NY and NJ)",
    "updated_at": "2026-09-23 19:33:28",
    "busiest_hour": "6 a.m. to 7 a.m.",
    "quietest_hour": "10 p.m. to 11 p.m.",
    "url": "https://securitywaittimes.com/airport/ewr/"
  },
  "notes": { ... },
  "generated_at": "2026-09-23T19:36:40+00:00"
}

2. Airport list

GET https://securitywaittimes.com/wp-json/swt/v1/airports

Parameters: none. Any query string is ignored and the full list comes back.

Response: version (currently 2), count (440) and airports. The order is not guaranteed, so sort by iata if you need a stable order. Each record has iata, name, city, state, region, lat, lng, tz (an IANA time zone), base_wait, terminals and checkpoints.

base_wait is the one model input specific to each airport, in minutes. It is not a live reading and not a current wait. Terminal and checkpoint names are the ones we use on the airport pages and can be shorter than the operator names.

{
  "iata": "ATL",
  "name": "Hartsfield-Jackson Atlanta International Airport",
  "city": "Atlanta",
  "state": "GA",
  "region": "South",
  "lat": 33.6407,
  "lng": -84.4277,
  "tz": "America/New_York",
  "base_wait": 18,
  "terminals": ["Domestic (North & South)", "International (Concourse F)"],
  "checkpoints": ["Main Checkpoint", "North Checkpoint", "..."]
}

3. Model parameters

GET https://securitywaittimes.com/wp-json/swt/v1/model

Parameters: none.

This file holds everything needed to recompute any modeled figure on the site:

  • primary.formula: standard = round(base_wait * hourly[h] * weekday[d]), with h the local hour and d the local weekday, 0 for Sunday. We checked this formula against all 16,800 airport, weekday and hour combinations in the primary model and it matched every one.
  • primary.hourly (24 values) and primary.weekday (7 values): the multipliers.
  • primary.precheck_formula: precheck = max(1, round(0.35 * standard)), checked for every standard wait from 1 to 120 minutes. primary.precheck_table lists the same values.
  • primary.airports (100) and simplified.airports (340): code, name, time zone and base wait.
  • simplified.formula and simplified.curve: the same daily shape scaled to each airport, with no weekday effect. PreCheck there is max(1, round(0.38 * standard)).
  • live: which airports have live feeds and what the feed replaces.

Update cadence

  • Live figures: read from the operator feeds about every 5 minutes. The schedule runs on WordPress, so a quiet hour on the site can stretch the gap.
  • Primary-model figures: recomputed on a schedule for the current local hour. updated_at tells you when.
  • Simplified-model figures: computed at the moment of each request.
  • Airport list and model parameters: change only when we edit the model.

Responses carry cache hints: 60 seconds for /wait and one hour for /airports and /model. There is no hard rate limit. Please cache for at least a minute, since the live feeds only change about every 5 minutes.

Using it

All 3 endpoints send Access-Control-Allow-Origin: *, so you can call them from a browser on any site.

curl https://securitywaittimes.com/wp-json/swt/v1/wait?iata=ORD

fetch('https://securitywaittimes.com/wp-json/swt/v1/wait?iata=ORD')
  .then(r => r.json())
  .then(d => console.log(d.airport.standard_minutes, d.airport.measurement));

If you only need a display, the free wait time widget does this for you in about 1.4 KB.

License

The data is free to use under Creative Commons Attribution 4.0 (CC BY 4.0). Credit “Security Wait Times” with a link to this page or to the airport page you used. It comes with no warranty. Do not use it where a wrong figure could put someone at risk.

Statistics built on this data

Change log

  • 7 October 2026: the 340 simplified-model airports now cap their typical peak at 1 minute below the lowest full-model peak in the same state, or at 9 minutes where a state has no full-model airport. Their standard_minutes and precheck_minutes can be lower than before. PreCheck stays at 38% of the standard-lane figure.
  • 26 September 2026: busiest_hour and quietest_hour now use the site time style, for example 6 a.m. to 7 a.m. and 11 a.m. to noon. They used to read 6-7 AM.
  • 23 September 2026: the 340 simplified-model airports now return their modeled wait from /wait; they returned unavailable before, although their pages showed a figure. precheck_measurement now reads live where a live feed publishes PreCheck. Added model to each record, sorted the full list by code, and added the /model endpoint.