script to make dmv road test appointment

Update 12/30/2018: I wrote it back in 2015 and never revisited, I am pretty sure it’s not working. Please only use this as reference if you want to invent your own.

This article only applies to California DMV road test.

Last month my wife wanted to take the behind-the-wheel drive test at DMV. We made an appointment on April 21st but we want to take the test earlier, and we know sometimes people just reschedule for different reasons and sometimes DMV releases new available time slots. As I believe in DRY principle I don’t want to sit in front of a computer and refresh the page forever to get a lucky chance. And the simple job should be easily done by some quick-and-dirty script.

I googled for such script, didn’t find a perfect script which just meets my needs but I found a script on Github for field office visit appointment. So, based on that, I simply changed the script to adapt to the behind-the-wheel test procedure, added “start date” so that we don’t make too early appointment, keep refreshing until we can get a better time. And we did.

Script can be found at my gist page and here is the no-more-maintained code:

import mechanize
from bs4 import BeautifulSoup
from datetime import datetime
import random
import time
 
 
TGT_DATE = 'April 21, 2015' #i.e. 'September 30, 2014'
OFFICE_ID = '548' # officeid for RWC DMV. See HTML code for other office ids
TASK = 'DT'
 
form_url = 'https://www.dmv.ca.gov/wasapp/foa/findDriveTest.do'
def schedule(targetDate,name,officeId,telNumber,birthday,dlNumber,fromDate=None):
    tels = telNumber.split('-')
    births = birthday.split('-')
    names = name.split(' ')
    if not fromDate:
        fromDate = datetime.today()
        from_date = datetime.today().strftime("%B %d, %Y")
    else:
        from_date = datetime.strptime(fromDate,'%B %d, %Y')
    tgt_date = datetime.strptime(targetDate,'%B %d, %Y')
    # Browser
    br = mechanize.Browser()
    br.open(form_url)
    br.select_form(name="ApptForm")
    br['officeId']=[officeId]
    br.find_control(name="requestedTask").value = ["DT"]
    br['firstName'] = names[0]
    br['lastName'] = names[1]
    br['telArea'] = tels[0]
    br['telPrefix'] = tels[1]
    br['telSuffix'] = tels[2]
    br['dlNumber'] = dlNumber
    br['birthMonth'] = births[0]
    br['birthDay'] = births[1]
    br['birthYear'] = births[2]
 
    result = br.submit()
    result_html =  br.response().read()
    soup = BeautifulSoup(result_html)
    results = soup.findAll('p',class_="alert")
    logString = ""
 
    for result in results:
        if ('2015' in result.get_text()):
            appt_text = result.get_text()
            logString += "Earliest Appointment found is %s" %(appt_text)
            appt_date = datetime.strptime(appt_text,'%A, %B %d, %Y at %I:%M %p')
 
            if appt_date <= tgt_date and appt_date>=from_date:
                logString+= "nCongratulations! You've found a date earlier than your target. Scheduling the appointment..."
                br.select_form(nr=4)
                r = br.submit()
 
                logString+= "nConfirming the appointment..."
                br.select_form(nr=4)
                r = br.submit()
                s = BeautifulSoup(br.response().read())
                logString += "nThe final step is to actually schedule it...Use it when necessary.n"
                br.select_form(nr=4)
                r = br.submit()
                s = BeautifulSoup(br.response().read())
                print s
                # logString += br #print out relevant info related to the appointment
                print logString
                with open("test.txt", "a") as myfile:
                    myfile.write(logString)
                return True
            else:
                logString += "nSorry there is no appointment available between date %s and %s"%(from_date,targetDate)
                logString += "n"
                print logString
                with open("test.txt", "a") as myfile:
                    myfile.write(logString)
                return False
 
while not schedule(TGT_DATE,'FIRST LAST',OFFICE_ID,'111-222-3333','01-30-1980','DL00001','April 13, 2015'):
    waitTime = random.randint(60,600)
    time.sleep(waitTime)

DMV office’s ID can be found at DMV’s own website, if you need to schedule at another place, please go there and find it. Or you may want to enhance the code if you want try more than one DMV offices at the same time.

Now she happily passed the test so I can open-source the code, and I can’t test it any more because DMV won’t let someone who already passed the test to make such appointment.