Own product · UX/UI · Full stack

PlatePing: live vanity plate checks with no API to call.

No state offers an API for vanity plate availability. So PlatePing drives each DMV’s own public tool with a headless browser, and tells you plainly where it can’t.

Live checks 4 state DMVs Format checks 50 states + DC

PlatePing with New Hampshire selected: the plate “PL8PING” returns “Available” from a live check, a plate preview below, and the map zoomed in on New Hampshire.
A live check against the New Hampshire DMV
Client
PlatePing, my own product
My role
Product, UX/UI design, front end and back end
Timeline
September 2026
Stack
Next.js 14 (App Router), TypeScript, Tailwind CSS, shadcn/ui, Playwright, d3-geo, Vercel
Live app
plateping-eight.vercel.app (opens in a new tab)
Source
GitHub (opens in a new tab)
Overview

A simple question with no easy answer.

Is the vanity plate I want still free? To find out, you usually have to find your state’s DMV site, click through its own multi-step form and decode its wording. Most states don’t offer a checker at all.

PlatePing puts that behind one search box. Pick a state, type a plate, and get a clear answer. For four states it’s a live answer from the DMV itself. For the rest it’s a format check against that state’s rules.

The problem

Three reasons nobody had built this.

01

No API anywhere

There is no national vanity plate API, and no state publishes one. The only source of truth is each DMV’s public web form.

02

Every state is different

Each form has its own steps, fields, wording and technology, from old ASP.NET postbacks to AJAX fragments.

03

Bots aren’t welcome

Some DMV sites sit behind Akamai bot protection, and some vendors forbid automation in their terms.

Research

Four states, four different forms.

I mapped each state’s flow in the browser’s network tab before writing any automation.

01

New Hampshire

A wizard: vehicle type, then plate type, then the plate. The result is read from a status indicator and sorted into available, taken or not allowed.

02

Florida

An ASP.NET WebForms page. Submit triggers a full-page postback, so the check waits for navigation and then reads a status label.

03

Ohio

Choosing Passenger and clicking “Check Availability” fires an AJAX request that returns an HTML fragment with a success or danger alert.

04

Pennsylvania

Redirects across PennDOT hosts, three postback steps, and the plate typed into one input per character.

Design

One search box, an honest answer.

Fast path first

The four live states sit above the search as one-tap chips. Every other state is one dropdown away, so the fastest path is also the most useful one.

Show the plate, show the place

The answer comes with a preview of the plate itself and a US map that zooms into the chosen state. The map is built with react-simple-maps and d3-geo, fitting each state to the frame.

Clear result states

Live checks return Available, Taken or Not allowed. Format checks say Format check passed, never “available,” because PlatePing can’t know that for those states.

History and themes

A Recent checks page keeps the last 20 lookups in local storage, on the device only. The interface works in light and dark mode.

A live New Hampshire check for “KLEP” showing “Not available” in red, with the plate preview and the map zoomed on New Hampshire.
Live check · taken
A California check for “GO2GTHR” showing “Format check passed” with a plate preview and the map zoomed on California.
Format check · California
PlatePing in dark mode: a live Florida check for “SUNNY” returns “Not available,” with the map zoomed on Florida.
Dark mode · a live Florida check
The Recent checks table: California GO2GTHR “Format valid,” New Hampshire KLEP “Taken” and New Hampshire PL8PING “Available,” each checked just now.
Recent checks, stored on this device only
Build

A headless browser behind every live check.

Each live state has its own API route that opens Chrome, fills in the DMV’s form like a person would, and turns the page into a clean result.

Live checks

  • Playwright drives each state’s public form. Every adapter documents the flow it relies on: URLs, selectors and the exact result wording.
  • All adapters return the same shape: available, taken, not allowed or error. They never throw.
  • A hard timeout (15 s locally, 25 s on Vercel) means a slow DMV can’t hang the app.

Running Chrome on Vercel

  • On Vercel, @sparticuz/chromium-min downloads a Chromium build at cold start, kept out of the bundle.
  • Locally it prefers the system Chrome, because Akamai blocks stock Chromium on some DMV sites.
  • An optional remote browser (a Browserless or Playwright endpoint) can take over for sites that block serverless IPs.

Guardrails

  • Rate limit of 10 checks per minute per IP, so PlatePing is a polite visitor.
  • Results are cached for 5 minutes, so repeat checks don’t hit the DMV again.
  • Block pages (Akamai “Access denied” and similar) are detected and reported as errors, not as wrong answers.

Format rules

  • Every other state gets a format check: length, allowed characters and at least one letter.
  • New Hampshire uses its own rules: up to 7 characters, 1–9 (no zero), and up to 2 non-consecutive symbols (&, +, -).
  • Plates are normalized before checking: spaces removed, uppercased, zero read as O.

One live check, start to finish

  1. RequestState and plate from the UI
  2. Rate limit10 per minute per IP
  3. Cache5-minute result cache
  4. Headless ChromeFills in the DMV’s public form
  5. ResultAvailable, taken, not allowed or error

Each live state has its own route (/api/check-nh, -fl, -oh, -pa) with the same steps. Errors are never cached.

Scope

Choosing what not to automate.

Only public tools

Live checks run only where a state publishes its own public availability tool. Most states don’t, so they get a format check instead of a guess.

Respecting terms

Texas has a checker, but its vendor’s terms forbid robots and scrapers. PlatePing keeps Texas to format checks and notes why in the code.

Built to break gracefully

These are unofficial integrations. If a DMV redesigns its page, the check returns a clear error instead of a wrong answer until the adapter is updated.

Results

Live, working and honest about its limits.

PlatePing is live on Vercel, and live checks return real answers from the DMVs in production.

Live DMV integrations
4
States with format checks
50 + DC
Repeat checks cached
5 min
  • Launched in September 2026 at plateping-eight.vercel.app, with the source public on GitHub.
  • Live checks for New Hampshire, Florida, Ohio and Pennsylvania, each through that state’s own public tool.
  • Format checks for every other state and DC, clearly labeled as format checks.
What I learned

Three things I’d carry into any project.

01

Read the network tab first

Mapping each form’s requests and responses before writing code made the adapters short and the edge cases predictable.

02

Design for the unhappy path

Timeouts, bot walls and redesigned pages are normal here. Typed results that never throw kept the UI simple.

03

Honesty is a feature

Saying “format check passed” instead of “available” is less impressive, but it’s the only answer users can trust.

What’s next

Where PlatePing goes from here.

  • Move the rate limit and cache to a shared store, so they hold across serverless instances
  • Scheduled smoke checks that flag when a DMV changes its page
  • More live states, wherever a public tool exists and its terms allow it
Keep exploring

More from this work.

Have a project in mind?

Tell me what you’re building. If I’m not the right fit, I’ll tell you that too.

or email hi@klep.dev
20-min intro call

Book a call

Pick a time that works for you. I’ll confirm by email with a meeting link.

Day

Time