← Back to all posts
DMS Signs API

Real-Time DMS Sign Messages API: What's on the Highway Signs Right Now

April 30, 2026 · 6 min read

Dynamic Message Signs — the big electronic boards over the highway — are the fastest traveler-information channel a state DOT controls. When a crash happens, the sign two miles upstream often updates before the incident appears in the public 511 feed. Amber alerts, travel times, lane closures, weather warnings, evacuation routes — it all flows through DMS first.

The catch: every state publishes its DMS inventory in a different format. Georgia uses Transnomis JSON. Texas iterates 25 districts of ASP.NET MVC. Mississippi exposes ASP.NET PageMethods. Wyoming wraps protobuf in an XOR cipher. Some publish a clean “current message” field; others give you three pages and a phase number you have to reassemble into the line that’s actually displayed.

Road511 normalizes all of it into one endpoint. One API call returns the live text on every DMS across 30+ jurisdictions. And we’re the only API that publishes a historical archive of message changes.

What You Get

curl "https://api.road511.com/api/v1/features?type=signs&jurisdiction=GA&limit=10" \
  -H "X-API-Key: your_key"
{
  "data": [
    {
      "id": "ga-sign-i85-042",
      "jurisdiction": "GA",
      "feature_type": "signs",
      "name": "I-85 NB at Clairmont Rd",
      "latitude": 33.8103,
      "longitude": -84.3179,
      "properties": {
        "message": "CRASH AHEAD / I-85 NB AT SR 42 / RIGHT LANE BLOCKED",
        "message_lines": [
          "CRASH AHEAD",
          "I-85 NB AT SR 42",
          "RIGHT LANE BLOCKED"
        ],
        "is_blank": false,
        "last_changed": "2026-04-30T14:22:11Z",
        "sign_type": "DMS"
      }
    }
  ],
  "total": 217,
  "has_more": true
}

The message field is the exact text currently on the sign with line breaks encoded as  / . message_lines is the same text pre-split for rendering. is_blank tells you whether the sign is dark or showing default text — useful for filtering out “DRIVE SAFELY” defaults so you only see signs that have something to say.

Filter to Just the Active Signs

Most DMS in any given inventory are blank or showing routine messages. The interesting ones — incidents, alerts, closures — are usually a tiny percentage. Combine type=signs with a bounding box and skip the blanks client-side:

curl "https://api.road511.com/api/v1/features?type=signs\
&bbox=-84.5,33.6,-84.2,33.9\
&limit=200" \
  -H "X-API-Key: your_key"

Returns every DMS in metro Atlanta. Filter is_blank === false in your client and you’re left with the handful of signs that have a message worth reading.

GeoJSON for Map Overlays

Same query, GeoJSON shape, ready to drop onto Leaflet, Mapbox, or QGIS:

curl "https://api.road511.com/api/v1/features/geojson?type=signs\
&bbox=-84.5,33.6,-84.2,33.9" \
  -H "X-API-Key: your_key"
const res = await fetch(
  'https://api.road511.com/api/v1/features/geojson'
  + '?type=signs&bbox=-84.5,33.6,-84.2,33.9',
  { headers: { 'X-API-Key': 'your_key' } }
);
const geojson = await res.json();

L.geoJSON(geojson, {
  filter: (f) => !f.properties.is_blank,
  pointToLayer: (f, latlng) => L.circleMarker(latlng, {
    radius: 7, color: '#f59e0b', fillOpacity: 0.85
  }),
  onEachFeature: (f, layer) => {
    const lines = f.properties.message_lines.join('<br>');
    layer.bindPopup(`
      <strong>${f.properties.name}</strong>
      <pre style="font-family: monospace; font-size: 12px">${lines}</pre>
    `);
  }
}).addTo(map);

Why Aggregating This Matters

DMS messages are a leading indicator. The traffic operator who runs the sign also runs the 511 feed, but the sign update happens first — sometimes ten or fifteen minutes before the event appears in the public incident list. Cross-referencing live sign text with traffic events gives you several things you can’t get from either feed alone:

Historical Message Archive

Here’s the part nobody else does: Road511 records every message change. The sign_message_history table stores only actual changes (not every poll), so you get a clean timeline of what each sign displayed and when.

curl "https://api.road511.com/api/v1/features/ga-sign-i85-042/history?days=7" \
  -H "X-API-Key: your_key"
{
  "feature_id": "ga-sign-i85-042",
  "history": [
    {
      "changed_at": "2026-04-30T14:22:11Z",
      "message": "CRASH AHEAD / I-85 NB AT SR 42 / RIGHT LANE BLOCKED"
    },
    {
      "changed_at": "2026-04-30T13:48:02Z",
      "message": "TRAVEL TIME / DOWNTOWN / 14 MIN"
    },
    {
      "changed_at": "2026-04-30T07:00:08Z",
      "message": ""
    }
  ]
}

This is data that doesn’t exist anywhere else publicly. No state DOT publishes a historical archive of DMS messages — the source feeds only ever show the current state of each sign. We started recording when we built the adapter, so the archive grows from each adapter’s onboarding date forward.

Coverage

DMS data lives in the signs feature type. We pull from every state and province that exposes a public sign feed. Counts below are approximate active inventory; specific signs come and go as DOTs install or retire hardware.

Jurisdiction Approx. signs Source platform
Michigan (MI)~487MiDrive (lazy-load detail)
Oregon (OR)~485TripCheck inventory + status join
Texas (TX)varies, 25 districtsTxDOT ITS
Montana (MT)~123Iteris ATIS CDN
North Dakota (ND)~100NDRoads Azure Blob
Mississippi (MS)~76MDOTtraffic ASP.NET
Alabama (AL)~73ALGO Traffic
Wyoming (WY)~151WTI 511 PBF (protobuf)
Ohio (OH)variesOHGO Public API
Oklahoma (OK)variesoktraffic.org (3-way join)
Georgia + 8 generic511varies per stateTransnomis
NEC (ME, NH, VT)variesCompass C2C XML
Kentucky, Tennessee, Virginia, Arkansasvariesstate-specific REST

If a state publishes DMS data, we ingest it. New states roll in regularly — the adapter pattern is one SQL insert and one fetch function per source.

Who Uses This

One Note on Polling and Freshness

DMS feeds are polled by Road511 on schedules between 1 and 5 minutes depending on the state, with adaptive backoff if a feed misbehaves. The last_changed field reflects when we first observed the new message; the actual sign change is at most one polling interval earlier. For the time-critical use cases (amber alerts, incidents), keep your client on a 30–60 second cache and you’ll see new messages within a couple minutes of the operator posting them.

Try It

See what every highway sign is saying right now

One API call returns the live message on every DMS across 30+ states and provinces — plus a historical archive nobody else publishes. Free 14-day trial. No credit card.

Get Free API Key Explore the Map