It’s a pain to check if a personalized license plate is available on the CA website:
- If it’s available, and you don’t necessarily want to buy that plate right then and there, it breaks the process and you have to start from the beginning, entering in your plate, your VIN, choosing your plate, and all of your other info all over again.
- If it’s not available, after trying 5 or 10 times and all of your wanted plates are taken, most people get frustrated and settle with something that they know will be available because they don’t have all day.
I set out to find a better way to check these in bulk. Specifically, to scrape the California DMV website for available license plates.
That’s when I landed on this guy’s code; it wasn’t working, and it hadn’t been updated in a couple years, but it was 80% completed:
It also had a handful of flaws:
- There were syntax errors regarding the viewport calculation
- It went way too fast, usually stumbling over itself or not giving the page enough time to load, which broke the script
- It would frequently erase the first character and type over itself. So you’d end up in a situation where it checks the word “TOAST” but the first letter was erased, so it would search “OAST”. This led to false positives/negatives.
- It didn’t have proper error/success handling
- It was inefficient and used too much resources
- It was single-threaded
Still, it had good bones so I used it as a starting off point. I made a number of powerful modifications to it:
- Multithreading, so I can run many different versions of this at once to speed up giant lists.
- Added rotating proxy support and a rotating residential proxy; essential so my IP doesn’t get blocked and I can scale the speed.
- Reusing the open browser windows when a license plate is taken. Going through the entire process from A-Z is only necessary if you get a “Success” since they won’t let you go “Back” in your browser. But if it’s failed, you can keep trying right there on the page. I modified the script accordingly which significantly sped it up. I split this into two functions; one that starts from the very beginning of the process, and one that backspaces 7 times to try again on the current browser window.
- Intelligent retries. Sometimes the page doens’t fully load, lags out, etc, so now it will retry automatically a few times.
- Improved success/error handling. Checking different elements for “Success” and “Taken” eliminated the false positives.
- Replace zeros (0) character with capital o (O). California doesn’t recognize the zero in their license plate availability checker, so I added some logic to swap this out automatically in the code so I don’t have to think about it.
- Added human-like delays between steps to give it enough time to load and to look more human.
- Runs silently. It now runs in headless mode so you aren’t seeing a bunch of browser windows open at once.
- Display the number of results per minute. Why not?
- Hardened it against critical script-breaking errors for large jobs. If something breaks, it kills the browser instance elegantly and retries with a new one without aborting the entire script.
The first test ran 80-100 license plate checks per minute!
I haven’t tried turning it up to 20 or 30 yet. Both my proxies and my machine are powerful enough so I don’t see why it wouldn’t work. But I’m not in a big rush and I don’t want to throw up any red flags. And 100 checks per minute is not slow by any means.
At a certain point, it made more sense to only show the “Available” plates that the tool found, since there were far more “Taken” ones. I’m running lists of tens of thousands of keywords at once so I don’t really care so much about the unavailable ones. This gave me much nicer results:
I gave it a bigger list and cranked up the multi-threading from 10 to 30 and I’m achieving over 220 results per minute now!
Anyway, kind of random, but it was a fun project! Hopefully I find a license plate that I like with this thing.