US Border Wait Times - CBP Crossings Ranked by Drive + Wait avatar

US Border Wait Times - CBP Crossings Ranked by Drive + Wait

Pricing

$20.00 / 1,000 query answereds

Go to Apify Store
US Border Wait Times - CBP Crossings Ranked by Drive + Wait

US Border Wait Times - CBP Crossings Ranked by Drive + Wait

US border wait times for the 85 land ports of entry on the Mexican and Canadian borders, from CBP's published figures, ranked by all-in time: the drive from your point plus the wait in your lanes (standard, SENTRI/NEXUS, Ready, FAST), for cars, trucks or pedestrians. JSON/CSV, pay per query.

Pricing

$20.00 / 1,000 query answereds

Rating

0.0

(0)

Developer

Dave Fergins

Dave Fergins

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

17 hours ago

Last modified

Share

US border wait times as plain JSON or CSV rows, for all 85 US land ports of entry on the Mexican and Canadian borders, ranked by all-in time from your starting point: the drive there plus the current wait once there, per lane type, for passenger, commercial or pedestrian traffic. The waits are US Customs and Border Protection's own published figures. The nearest crossing is often not the fastest: a crossing 50 km further out with a 10-minute wait beats the one next door at 125 minutes, and only an all-in number shows it.

The Actor is a thin client: it sends each query you give it to the border wait service, charges one event per query the service answers, and writes the answer to the dataset as one summary row plus one row per crossing, fastest all-in first. A run takes seconds and uses 256 MB. You need no API key or account with any data provider; the Actor carries its own credential.

Border crossings ranked by drive time plus the live CBP wait

One query is a starting point (lat, lon), a vehicle type (passenger, commercial or pedestrian; each has its own lanes and waits) and the lanes you may use: standard only by default, plus SENTRI/NEXUS, Ready and FAST when you hold them. Each crossing row carries port, crossing (the crossing's own name when the port has several), port_number, border (Mexican or Canadian), port_status, hours, distance_km (straight-line from your point), drive_minutes (at the assumed speed, default 70 km/h), the best usable lane flattened as best_lane_lane, best_lane_status, best_lane_delay_minutes, best_lane_lanes_open, best_lane_update_time and best_lane_reported, and total_minutes, which is drive_minutes plus the best lane's wait and the ranking key. The full per-lane list stays nested in lanes, and construction_notice appears when CBP posts one.

best_lane_reported matters: CBP reports nothing at all for some lanes, and those are shown as unreported (false) rather than as a zero-minute wait. radius limits how far to look in km (0 or empty: no limit) and limit how many crossings to return (default 5).

Several starting points in one run

The top-level fields are the first query and the defaults for every other. Add points as a list of "lat,lon" strings for more starting points with the same settings, or queries as a list of objects using the same field names for anything else, for instance a commercial query with the FAST lane next to a passenger one. A queries object with its own point does not inherit the top-level one; one that only changes a setting runs from the top-level point. A run may hold at most 25 queries, and each query the service answers is one billable event.

Example input

{
"lat": 32.7157,
"lon": -117.1611,
"vehicle": "passenger",
"lanes": ["standard", "SENTRI/NEXUS"],
"radius": 0,
"speed": 70,
"limit": 5,
"place": "San Diego",
"points": ["32.5422,-116.9735"],
"queries": [{ "lat": 31.7619, "lon": -106.485, "vehicle": "commercial", "lanes": ["standard", "FAST"], "place": "El Paso" }]
}

That run is three queries: passenger traffic from downtown San Diego with a SENTRI/NEXUS card, the same from Chula Vista, and commercial traffic from El Paso with FAST. Field names are the service's own, so a queries object is exactly the query it sends.

Output: example rows, CSV views and the OUTPUT record

Every row starts with the same eight columns: scout, row_type (summary or crossing), query_index (1-based position in the run), query (the normalised query as sent), as_of (CBP's feed date and time), receipt, source and disclaimer. Then the row's own fields. A crossing row looks like this:

{
"scout": "crossings",
"row_type": "crossing",
"query_index": 1,
"query": { "lanes": ["standard", "SENTRI/NEXUS"], "lat": 32.7157, "limit": 5, "lon": -117.1611, "place": "San Diego", "vehicle": "passenger" },
"as_of": "10/8/2026 13:00:00",
"receipt": "",
"source": "U.S. Customs and Border Protection border wait times (bwt.cbp.gov), public domain",
"disclaimer": "Wait times are US Customs and Border Protection's own published figures ...",
"rank": 1,
"port": "Otay Mesa",
"crossing": "",
"port_number": "250601",
"border": "Mexican Border",
"port_status": "Open",
"hours": "24 hrs/day",
"distance_km": 22.9,
"drive_minutes": 20,
"total_minutes": 25,
"best_lane_lane": "SENTRI/NEXUS",
"best_lane_status": "no delay",
"best_lane_delay_minutes": 5,
"best_lane_lanes_open": 3,
"best_lane_update_time": "At 1:00 pm PDT",
"best_lane_reported": true,
"lanes": [{ "lane": "standard", "status": "delay", "delay_minutes": 25, "lanes_open": 10, "update_time": "At 1:00 pm PDT", "reported": true }],
"vehicle": "passenger"
}

The summary row for each query carries vehicle, eligible_lanes (the lanes ranked on), crossings_count, crossings_without_coordinates (ports skipped because their location is unknown) and the plain-language summary. The dataset has two table views: summary (one line per query) and crossings (one line per crossing). Filter on row_type when you export both as one CSV. The run's OUTPUT key-value record holds the service's response for every query verbatim, keyed q1, q2, ..., each with the query it answered, plus an errors map for any query that failed.

Pricing: pay per query answered

One query-answered event per query the service answered, whatever the number of crossings: one starting point is one event, ten is ten events. Rows are never billed individually, so limit changes the size of the dataset, not the price. A query the service refuses (the service warming up, a malformed lane list) is not charged, and the run still succeeds with the queries that worked; only a run where every query failed ends as failed. A query with no open crossing in range is answered, charged once and writes its summary row saying so. The per-event price is on this page's Pricing tab. A run every 15 minutes for one starting point is about 2,900 events a month; hourly is about 720.

Use cases: commuter and trucking dispatch, travel apps and dashboards

  • Commuters and cross-border workers: which crossing to head for right now, counting the drive, with the SENTRI/NEXUS or Ready lane when you hold one.
  • Trucking and dispatch: commercial lanes with FAST, ranked by the all-in time from the yard, on a schedule.
  • Travel and logistics apps: the per-lane waits for the 85 ports in one flat table, with CBP's own update time on every row.
  • Spreadsheets and dashboards: export the crossings view as CSV or attach Apify's Google Sheets integration so every scheduled run appends its rows and the wait history builds itself.
  • AI agents and automations: like any public Actor it can be called through the Apify API, a webhook or Apify's MCP server, with the same input and the same dataset.

Data source and attribution

The waits are U.S. Customs and Border Protection's published border wait times (bwt.cbp.gov), public domain, covering 85 US ports of entry (30 on the Canadian border, 55 on the Mexican border). Every row carries the attribution in source and the service's disclaimer verbatim:

Wait times are US Customs and Border Protection's own published figures and can change sharply within minutes; CBP reports nothing at all for some lanes, and those are shown as unreported rather than as zero. Drive times are straight-line estimates at an assumed average speed, not routed directions. Confirm at the crossing.

FAQ

Which crossings are covered? The 85 US land ports of entry CBP publishes wait times for: 55 on the Mexican border and 30 on the Canadian border. Ports whose location CBP does not publish are skipped and counted in crossings_without_coordinates.

How fresh are the waits? They are CBP's own figures as published at as_of, with each lane's update_time in CBP's words. They can change sharply within minutes, so a schedule is the way to track them.

Is the drive time a routed estimate? No. distance_km is straight-line and drive_minutes divides it by the assumed speed (default 70 km/h). It is good enough to rank crossings against each other, not a navigation estimate.

What are the lane types? standard (everyone), SENTRI/NEXUS (trusted-traveller programmes), Ready (RFID-enabled documents) and FAST (commercial trusted-shipper). List the ones you may use in lanes; the ranking uses the best usable lane at each crossing.

What does reported = false mean? CBP published no wait for that lane at that time. The row says so instead of showing a zero, so an unreported lane never looks like an empty one.

Can I check several starting points in one run? Yes: points for more "lat,lon" starting points with the same settings, or queries for a list of full query objects. At most 25 queries per run, one event each.

Do I need an API key? No. The Actor carries its own credential for the border wait service; you only give it the queries.

Why did one query fail while the others worked? The service answers each query on its own; a query it cannot answer is recorded in the status message and the OUTPUT record's errors map, skipped without charge, and the rest continue.