🚨 Emergency Numbers
999Emergency Services NHNational Highways 🔧Get Breakdown Help
🚨 Emergency? Call 999 · Motorway breakdown? 0300 123 5000
LIVE TRAFFIC
Loading incidents...
0

Start typing to search

Find traffic updates, service providers, tools & more

API Documentation

Live UK road incident data and historical police collision records, over a REST API returning JSON.

Overview

There are two distinct products here, and most integrations only need one.

ProductWhat it isEndpoint
Live trafficMAINWhat is happening on the roads right now. Two separate feeds — motorway and London. This is what digital signage uses.action=live
Historical collisions551,000 police-recorded collision records from 2020 onward, with vehicle and casualty detail. Used for road safety analysis, insurance and legal work.action=collision
action=road
action=stats
action=blackspot
action=lookup

Base URL  https://www.uktrafficupdates.uk/api/data-api.php

Authentication

Pass your key as a query parameter or an HTTP header. Every request needs one.

# Query parameter
GET /api/data-api.php?key=uktu_signage_xxxx&action=ping

# HTTP header
GET /api/data-api.php?action=ping
X-API-Key: uktu_signage_xxxx

Check your key first

action=ping confirms the key works and returns a live snapshot of current conditions — active counts per feed and the busiest roads at that moment. Useful as a first call because it shows the real scale of the data before you write any template code.

GET?key=xxx&action=ping
{
  "status": "ok",
  "organisation": "Example Media Ltd",
  "tier": "signage",
  "timestamp": "2026-08-16T06:13:02+01:00",
  "live_now": {
    "active_total": 81,
    "feeds": {
      "motorway": { "source": "nh",  "active": 11,
                    "covers": "Motorways and trunk A-roads in England (National Highways)" },
      "london":   { "source": "tfl", "active": 70,
                    "covers": "London road network (Transport for London)" }
    },
    "busiest_roads": [
      { "road": "M27", "active": 3 },
      { "road": "M25", "active": 2 }
    ],
    "data_updated": "2026-08-16T06:12:01+01:00",
    "stale": false,
    "try_these": [
      "?key=YOUR_KEY&action=live&feed=motorway",
      "?key=YOUR_KEY&action=live&feed=london"
    ]
  }
}

live_now is always genuine current data. It is never sample or placeholder content. If the roads are clear it will say so.

Rate limits

TierPer hourPer dayPriceIntended for
Trial10100FreeEvaluation and prototyping
Starter1001,000£199/moSolicitors, local authorities, researchers
Professional5005,000£499/moFleet operators, insurers, regional councils
Signage60,0001,000,000From £999/moSignage estates up to roughly 2,500 screens
Enterprise200,0005,000,000Contact usLarger estates, subject to infrastructure review

Every response carries meta.calls_remaining_hour and meta.calls_remaining_day. Signage tiers are priced per estate, not per screen.

Errors

Errors return status: "error" with a message. Check the HTTP status code as well as the body.

CodeMeaning
200Success
304Not Modified — nothing has changed since your last request. Empty body. See ETag.
400Bad request — check your parameters
401Missing or invalid API key
404Record not found
429Rate limit exceeded
500Server error — contact support
503Live cache rebuilding. Transient; retry shortly.

Live traffic — two feeds, pick one

These are two separate products for two different kinds of site.

A driver at a motorway services has no use for a film crew closing Abbey Road. A screen in central London has no use for congestion on the M6. Sending both to one screen is noise, not coverage.

Choose one feed per screen. If you omit feed you will receive both merged, which is rarely what a screen wants.

Motorway feed  feed=motorway

Source  National Highways NTIS Event Data and Dev Portal API, under licence.

Covers  Motorways and trunk A-roads across England.

Contains  Live incidents — collisions, closures, lane restrictions, vehicle fires, congestion. Typically short-lived and unplanned.

Typical site  Motorway service areas, trunk-road retail, fuel forecourts, logistics depots.

GET?key=xxx&action=live&feed=motorway&road=M6

Lane counts and National Highways' own delay figures are present where published. contraflow is a real true or false on this feed.

London feed  feed=london

Source  Transport for London open data.

Covers  The London road network, including borough roads.

Contains  Disruptions — utility and water works, temporary signals, filming, events, planned closures. Often runs for days or weeks rather than hours.

Typical site  London retail, transport hubs, city-centre and borough screens.

GET?key=xxx&action=live&feed=london&road=A10

lanes_closed, delay_mins and contraflow are null on this feed — TfL do not publish them as structured fields. Where a contraflow or lane closure exists it appears in description.

Parameters

GET?key=xxx&action=live&feed=motorway&road=M6&lat=52.31&lng=-1.11&nearest=5
ParameterTypeDescription
feedstringPICK ONE motorway or london. Omitting it returns both merged.
roadstringoptional Road identifier, e.g. M6, A10, A205. The recommended way to scope a fixed screen.
lat lngfloatoptional Screen coordinates. Latitude 49–61, longitude −8 to 2. Adds distance_miles to every incident and sorts nearest first.
radius_milesfloatoptional Search radius in miles, 0.06–100. Default 15. Requires lat and lng.
radiusintoptional Same in metres, 100–160,934. radius_miles wins if both are given.
nearestintoptional Return the N closest incidents, 1–50, ignoring radius entirely. Requires lat and lng.
categorystringoptional Partial match on incident category, e.g. Collision, Utility.
regionstringoptional south east, south west, midlands, north west, north east, east, london.
limitintoptional Maximum results, 1–200. Default 50.
sourcestringlegacy nh or tfl. Equivalent to feed; still supported.

Query patterns

Configure screens by road, not by radius.

A driver at Corley services cares what is on the M6 ahead of them, far more than what falls inside a circle drawn around the building. An incident forty miles up their own carriageway matters enormously; one five miles away on a different road does not matter at all.

“Which road is this screen on?” is also easier to configure once per site than a radius that needs tuning per location.

PatternQueryBest for
CorridorBESTfeed=motorway&road=M6Motorway services and trunk-road sites. Everything on that road, distance irrelevant.
Corridor + proximityBESTfeed=motorway&road=M6&lat=..&lng=..&nearest=5As above, ordered by closeness to the screen so the most relevant appears first.
Nearestfeed=london&lat=..&lng=..&nearest=3City screens, or any site that must always show something. Ignores distance entirely.
Radiusfeed=london&lat=..&lng=..&radius_miles=5Strict “within X miles”. Returns nothing when roads are clear — your template must handle an empty list.
# Corridor — everything on the M6
?key=xxx&action=live&feed=motorway&road=M6

# Corridor + proximity — M6, five closest to this screen first
?key=xxx&action=live&feed=motorway&road=M6&lat=52.31&lng=-1.11&nearest=5

# Nearest — always returns something, however far
?key=xxx&action=live&feed=london&lat=51.51&lng=-0.13&nearest=3

# Radius — strict, may return nothing
?key=xxx&action=live&feed=london&lat=51.51&lng=-0.13&radius_miles=5

Quiet periods are normal

UK roads are frequently clear. On a quiet afternoon there may be fewer than twenty active motorway incidents nationally, and a strict radius query will legitimately return "count": 0 for long stretches, particularly overnight and at weekends.

This is accurate data, not a fault. A well-built template can present it positively — “No incidents reported on the M6 nearby” is useful to a driver. If a screen must always carry content, use nearest rather than radius: it returns the closest incidents whatever the distance, with distance_miles attached, so your template decides what is worth showing.

Response fields

{
  "status": "ok",
  "count": 2,
  "cached_at": "2026-08-16T06:13:02+01:00",
  "data_updated_at": "2026-08-16T06:12:01+01:00",
  "stale": false,
  "stale_reason": null,
  "source_counts": { "nh": 11, "tfl": 70 },
  "filters": { "feed": "motorway", "source": "nh", "road": "M6" },
  "incidents": [
    {
      "id": 566245,
      "ref": "dp_b6f791f8560fe87a0308",
      "source": "nh",
      "road": "M6",
      "category": "Road Or Carriageway Or Lane Management",
      "title": "M6 southbound within J18",
      "description": "M6 southbound within J18. Lane closures. Currently active.",
      "location": "M6 southbound within J18",
      "lanes_closed": "1 of 3 lanes closed",
      "contraflow": false,
      "delay_mins": null,
      "expected_clear": null,
      "lat": 53.201946,
      "lng": -2.387504,
      "started": "2026-08-16T05:24:01+01:00",
      "updated": "2026-08-16T05:30:01+01:00",
      "distance_miles": 4.2,
      "attribution": "Powered by National Highways' Transport Data Feeds"
    }
  ],
  "attribution": "Powered by National Highways' Transport Data Feeds. This credit must appear wherever the data is displayed."
}

Incident fields

FieldNotes
id / refInternal identifier, and the upstream reference from National Highways or TfL. ref is stable across updates and is the one to use for deduplication.
sourcenh or tfl. Matches the feed you requested.
roadRoad identifier. On the London feed this is extracted from TfL's location text, which carries it as a bracketed prefix.
titleShort headline, suitable for a signage header line.
descriptionFull incident text. HTML entities decoded, whitespace flattened to a single line.
categoryIncident classification, e.g. Collision, Vehicle Fire, Utility works, Filming. Useful for separating live incidents from planned works on the London feed.
locationJunction range or location description where known.
lanes_closede.g. 1 of 3 lanes closed. Motorway feed only; null or empty on the London feed.
contraflowtrue or false on the motorway feed, where National Highways publish it. Always null on the London feed — TfL do not publish it, and false would assert something we were not told.
delay_minsNational Highways' own delay figure in minutes, or null. Never estimated by us. Always null on the London feed.
expected_clearPublished clearance estimate, or null. Never inferred. Estimates are not always revised, so do not render this as a live countdown.
lat / lngIncident coordinates. Passed through from source without adjustment.
started / updatedISO 8601 with offset. updated confirms the incident is still being seen in the feed.
distance_miles
distance_m
Present only when lat and lng were supplied. Both units always returned.
attributionThe credit line for this specific incident. Must be displayed. See Attribution.

Fields with no value are returned empty or null rather than omitted, so the object shape is identical across every incident and both feeds.

There is deliberately no severity field

The live feeds do not publish a severity grade. Source data grades inconsistently — Transport for London mark almost everything “minimal” regardless of real impact — and a severity label that is wrong is worse than none. A screen that says “minor” beside a full closure teaches drivers to ignore the next one.

The purpose is to warn that something is there. The road, the junction range, the lane detail and the delay give a driver what they need to judge it themselves. Historical collision records do carry severity, because that is police-recorded fact rather than a live estimate.

Behaviour & limits

Units

Distances are returned in both miles and metres on every incident. For the search radius you may pass radius_miles or radius; miles wins if both are supplied. The filters block echoes back what was actually applied.

Timestamps

All timestamps are ISO 8601 with an explicit UTC offset, for example 2026-08-16T06:13:02+01:00. The offset moves between +01:00 and +00:00 across the year — parse the offset rather than assuming one.

ETag and 304 Not Modified

Every live response carries an ETag scoped to your exact query. Send it back as If-None-Match and you will receive 304 with an empty body when nothing has changed. At scale this is the difference between transferring a full payload on every poll and transferring almost nothing.

# First request
GET ?key=xxx&action=live&feed=motorway&road=M6
→ 200 OK
→ ETag: "a1b2c3d4e5"

# Subsequent request
GET ?key=xxx&action=live&feed=motorway&road=M6
If-None-Match: "a1b2c3d4e5"
→ 304 Not Modified   (empty body — reuse your cached copy)

How often to poll

The cache regenerates every five minutes, so polling faster than that returns 304 and gains nothing but call count. 60 to 120 seconds is the sensible band — tight enough to pick up a change promptly, without burning your allowance on empty responses.

IntervalPer screen2,500 screensComment
Every 30s120/hr300,000/hrExceeds the signage ceiling. No freshness benefit.
Every 60s60/hr150,000/hrAbove the signage ceiling at full estate size.
Every 90–120s30–40/hr75,000–100,000/hrRecommended. Comfortably within signage limits.
Every 5 min12/hr30,000/hrMatches cache cadence exactly. Lowest volume.

If your player architecture pulls centrally — a CMS fetching once per road or region and distributing to players — volumes are dramatically lower and a Professional tier may be sufficient. Tell us how your estate fetches and we will size it with you rather than guessing.

Stale data detection

If the upstream feed stops updating for more than 90 minutes, the response sets stale to true with a reason. Your template must check this and hide the widget or clearly label the data, rather than presenting stale incidents as current.

{
  "stale": true,
  "stale_reason": "NTIS data has not updated in 127 minutes. The feed may have stopped."
}

Sensitive content

Incident text is filtered before it reaches this API. Incidents involving people in distress, fatalities or police operations are suppressed and returned only as “Police incident”, with the free-text detail removed. Structural detail — road, junction, lane counts — is retained, since it carries no sensitive information and a driver still needs it.

Filtering is applied when the cache is generated, so the raw text never enters an API response. You must not attempt to circumvent or supplement it.

Attribution — required

Every response includes an attribution field, both at the top level and on each incident. It reflects the sources actually present in that response.

FeedRequired credit
feed=motorwayPowered by National Highways' Transport Data Feeds
feed=londonPowered by TfL Open Data

This credit must appear wherever the data is displayed — on every screen, not only on your own site. It is a condition of our upstream licences and is not negotiable. National Highways' branding guidelines apply to their credit; ask us for a copy.

Historical collision records

A separate dataset from the live feeds: 551,000 police-recorded collisions from the Department for Transport's STATS19 release, with linked vehicle and casualty records. Published annually, typically in September.

These records do carry severity — fatal, serious, slight — because it is police-recorded fact.

collision — one record in full

GET?key=xxx&action=collision&ref=2024010123456

Returns the collision with every linked vehicle and casualty. ref is the accident index, obtained from road or lookup.

road — collisions on a named road

GET?key=xxx&action=road&road=M25&severity=fatal&year=2024&limit=50&page=1
roadREQUIRED e.g. M25
severityoptional fatal, serious, slight
yearoptional e.g. 2024
limit / pageoptional Max 100 per page, default 50

stats — aggregates for a road

GET?key=xxx&action=stats&road=M25

Totals, severity split, year-by-year trend and weather breakdown.

blackspot — danger scoring

GET?key=xxx&action=blackspot&road=M25

Danger score, risk level and the worst junctions on that road.

lookup — collisions near a point

GET?key=xxx&action=lookup&lat=51.5074&lng=-0.1278&radius_miles=0.3
lat / lngREQUIRED Latitude 49–61, longitude −8 to 2
radius_milesoptional 0.03–1.24 miles, default 0.31
radiusoptional 50–2,000 metres, default 500

Deliberately tighter than the live endpoint — this is junction-level historical search, and a wide radius would return thousands of rows.

Data sources

SourceFeedsCoverage and update cycle
National Highways
NTIS Event Data & Dev Portal
feed=motorwayMotorways and trunk A-roads in England. Event-driven push, effectively real time.
Transport for London
TfL open data
feed=londonLondon road network. Refreshed every five minutes.
Department for Transport
STATS19
Historical endpointsAll UK roads, 2020 onward. 551,000 collision records. Annual release.

National Highways data is supplied under the NH Transport Data Feeds Licence. STATS19 is published under the Open Government Licence v3.0. TfL data is published under TfL's open data terms.

Pricing

TierLimitsPriceIncludes
Trial10/hr · 100/dayFreeAll endpoints. Same-day access.
Starter100/hr · 1,000/day£199/moAll endpoints including live.
Professional500/hr · 5,000/day£499/moAll endpoints. Priority support.
Signage60,000/hr · 1,000,000/day£499–999/moSignage estates up to 1,000 screens. ETag support, geo queries, road-scoped feeds.
Enterprise200,000/hr · 5,000,000/day£1,999+/moEstates over 1,000 screens, white-label, bespoke endpoints, SLA. Subject to infrastructure review.

Signage and enterprise — priced by estate

Signage licensing is priced by the size of your estate rather than by call volume, because what you are buying is coverage across your sites. One licence covers every screen in the band.

Estate sizeMonthlyIncludes
Up to 250 screens£499Signage tier. Both feeds. Email support.
Up to 1,000 screens£999Signage tier. Both feeds. Email support.
Up to 2,500 screens£1,999Enterprise tier. Both feeds. Priority support.
Over 2,500 screensFrom £2,999Enterprise tier. Scoped with you, subject to infrastructure review.

A one-off integration fee of £2,500 applies to signage and enterprise agreements, covering template consultation and developer support during build.

Billed monthly in arrears, 30-day terms. Multi-year commitments attract a discount — ask. Historical collision reports and bespoke road safety analysis are quoted separately.

Your obligations

ObligationDetail
AttributionDisplay the credit line for the feed you use, wherever the data appears. A condition of our upstream licences; omission is a material breach.
Respect the stale flagWhen stale is true, hide the data or clearly label it as potentially outdated. Presenting stale data as current on a public screen is not acceptable.
Do not circumvent filteringIncident text is filtered for sensitive content before it reaches you. Do not attempt to reverse, supplement or work around it.
No redistributionYou may display the data to your end users. You may not resell API access or redistribute raw data to third parties without written consent.
CachingDo not cache responses for longer than five minutes. Use ETag and 304 for efficient polling instead.
Rate limitsStay within your tier. Sustained abuse may result in suspension. Contact us to upgrade.

Terms

Use of this API is subject to our Terms and Conditions and Privacy Policy.

The data originates from third-party government sources under licences that may be modified, suspended or terminated by those providers at any time and without cause. We cannot guarantee uninterrupted supply. Data is provided “as is” without warranty as to accuracy, completeness or timeliness, and must not be relied upon for safety-critical decisions. Our total liability is capped at the fees paid in the preceding twelve months. Digital signage and public display use requires a separate commercial agreement — contact us.

Request access

Trial keys are free and available same day, with full endpoint access. Signage and enterprise access is scoped to your estate — get in touch and we will size it with you.

Request access → data@uktrafficupdates.uk

📢 Your ad here · 30,000+ followers across TikTok, YouTube and Instagram Advertise here →