Find traffic updates, service providers, tools & more
Live UK road incident data and historical police collision records, over a REST API returning JSON.
There are two distinct products here, and most integrations only need one.
| Product | What it is | Endpoint |
|---|---|---|
| Live trafficMAIN | What is happening on the roads right now. Two separate feeds — motorway and London. This is what digital signage uses. | action=live |
| Historical collisions | 551,000 police-recorded collision records from 2020 onward, with vehicle and casualty detail. Used for road safety analysis, insurance and legal work. | action=collisionaction=roadaction=statsaction=blackspotaction=lookup |
Base URL https://www.uktrafficupdates.uk/api/data-api.php
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
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.
{
"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.
| Tier | Per hour | Per day | Price | Intended for |
|---|---|---|---|---|
| Trial | 10 | 100 | Free | Evaluation and prototyping |
| Starter | 100 | 1,000 | £199/mo | Solicitors, local authorities, researchers |
| Professional | 500 | 5,000 | £499/mo | Fleet operators, insurers, regional councils |
| Signage | 60,000 | 1,000,000 | From £999/mo | Signage estates up to roughly 2,500 screens |
| Enterprise | 200,000 | 5,000,000 | Contact us | Larger 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 return status: "error" with a message. Check the HTTP status code as well as the body.
| Code | Meaning |
|---|---|
200 | Success |
304 | Not Modified — nothing has changed since your last request. Empty body. See ETag. |
400 | Bad request — check your parameters |
401 | Missing or invalid API key |
404 | Record not found |
429 | Rate limit exceeded |
500 | Server error — contact support |
503 | Live cache rebuilding. Transient; retry shortly. |
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.
feed=motorwaySource 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.
Lane counts and National Highways' own delay figures are present where published. contraflow is a real true or false on this feed.
feed=londonSource 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.
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.
| Parameter | Type | Description |
|---|---|---|
feed | string | PICK ONE motorway or london. Omitting it returns both merged. |
road | string | optional Road identifier, e.g. M6, A10, A205. The recommended way to scope a fixed screen. |
lat lng | float | optional Screen coordinates. Latitude 49–61, longitude −8 to 2. Adds distance_miles to every incident and sorts nearest first. |
radius_miles | float | optional Search radius in miles, 0.06–100. Default 15. Requires lat and lng. |
radius | int | optional Same in metres, 100–160,934. radius_miles wins if both are given. |
nearest | int | optional Return the N closest incidents, 1–50, ignoring radius entirely. Requires lat and lng. |
category | string | optional Partial match on incident category, e.g. Collision, Utility. |
region | string | optional south east, south west, midlands, north west, north east, east, london. |
limit | int | optional Maximum results, 1–200. Default 50. |
source | string | legacy nh or tfl. Equivalent to feed; still supported. |
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.
| Pattern | Query | Best for |
|---|---|---|
| CorridorBEST | feed=motorway&road=M6 | Motorway services and trunk-road sites. Everything on that road, distance irrelevant. |
| Corridor + proximityBEST | feed=motorway&road=M6&lat=..&lng=..&nearest=5 | As above, ordered by closeness to the screen so the most relevant appears first. |
| Nearest | feed=london&lat=..&lng=..&nearest=3 | City screens, or any site that must always show something. Ignores distance entirely. |
| Radius | feed=london&lat=..&lng=..&radius_miles=5 | Strict “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
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.
{
"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."
}
| Field | Notes |
|---|---|
id / ref | Internal identifier, and the upstream reference from National Highways or TfL. ref is stable across updates and is the one to use for deduplication. |
source | nh or tfl. Matches the feed you requested. |
road | Road identifier. On the London feed this is extracted from TfL's location text, which carries it as a bracketed prefix. |
title | Short headline, suitable for a signage header line. |
description | Full incident text. HTML entities decoded, whitespace flattened to a single line. |
category | Incident classification, e.g. Collision, Vehicle Fire, Utility works, Filming. Useful for separating live incidents from planned works on the London feed. |
location | Junction range or location description where known. |
lanes_closed | e.g. 1 of 3 lanes closed. Motorway feed only; null or empty on the London feed. |
contraflow | true 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_mins | National Highways' own delay figure in minutes, or null. Never estimated by us. Always null on the London feed. |
expected_clear | Published clearance estimate, or null. Never inferred. Estimates are not always revised, so do not render this as a live countdown. |
lat / lng | Incident coordinates. Passed through from source without adjustment. |
started / updated | ISO 8601 with offset. updated confirms the incident is still being seen in the feed. |
distance_milesdistance_m | Present only when lat and lng were supplied. Both units always returned. |
attribution | The 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.
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.
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.
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.
cached_at — when the cache was last writtendata_updated_at — when the underlying data last changed. Use this for any freshness indicator.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)
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.
| Interval | Per screen | 2,500 screens | Comment |
|---|---|---|---|
| Every 30s | 120/hr | 300,000/hr | Exceeds the signage ceiling. No freshness benefit. |
| Every 60s | 60/hr | 150,000/hr | Above the signage ceiling at full estate size. |
| Every 90–120s | 30–40/hr | 75,000–100,000/hr | Recommended. Comfortably within signage limits. |
| Every 5 min | 12/hr | 30,000/hr | Matches 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.
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."
}
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.
Every response includes an attribution field, both at the top level and on each incident. It reflects the sources actually present in that response.
| Feed | Required credit |
|---|---|
feed=motorway | Powered by National Highways' Transport Data Feeds |
feed=london | Powered 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.
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.
Returns the collision with every linked vehicle and casualty. ref is the accident index, obtained from road or lookup.
road | REQUIRED e.g. M25 |
severity | optional fatal, serious, slight |
year | optional e.g. 2024 |
limit / page | optional Max 100 per page, default 50 |
Totals, severity split, year-by-year trend and weather breakdown.
Danger score, risk level and the worst junctions on that road.
lat / lng | REQUIRED Latitude 49–61, longitude −8 to 2 |
radius_miles | optional 0.03–1.24 miles, default 0.31 |
radius | optional 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.
| Source | Feeds | Coverage and update cycle |
|---|---|---|
| National Highways NTIS Event Data & Dev Portal | feed=motorway | Motorways and trunk A-roads in England. Event-driven push, effectively real time. |
| Transport for London TfL open data | feed=london | London road network. Refreshed every five minutes. |
| Department for Transport STATS19 | Historical endpoints | All 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.
| Tier | Limits | Price | Includes |
|---|---|---|---|
| Trial | 10/hr · 100/day | Free | All endpoints. Same-day access. |
| Starter | 100/hr · 1,000/day | £199/mo | All endpoints including live. |
| Professional | 500/hr · 5,000/day | £499/mo | All endpoints. Priority support. |
| Signage | 60,000/hr · 1,000,000/day | £499–999/mo | Signage estates up to 1,000 screens. ETag support, geo queries, road-scoped feeds. |
| Enterprise | 200,000/hr · 5,000,000/day | £1,999+/mo | Estates over 1,000 screens, white-label, bespoke endpoints, SLA. Subject to infrastructure review. |
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 size | Monthly | Includes |
|---|---|---|
| Up to 250 screens | £499 | Signage tier. Both feeds. Email support. |
| Up to 1,000 screens | £999 | Signage tier. Both feeds. Email support. |
| Up to 2,500 screens | £1,999 | Enterprise tier. Both feeds. Priority support. |
| Over 2,500 screens | From £2,999 | Enterprise 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.
| Obligation | Detail |
|---|---|
| Attribution | Display 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 flag | When 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 filtering | Incident text is filtered for sensitive content before it reaches you. Do not attempt to reverse, supplement or work around it. |
| No redistribution | You may display the data to your end users. You may not resell API access or redistribute raw data to third parties without written consent. |
| Caching | Do not cache responses for longer than five minutes. Use ETag and 304 for efficient polling instead. |
| Rate limits | Stay within your tier. Sustained abuse may result in suspension. Contact us to upgrade. |
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.