Introduction
Similar to many places, RIT offers parking spaces to those who do not have a parking pass for a small hourly fee of $1/hour. The process is simple — register an account, add your personal information, register your license plate, and pay for the amount of time you plan on using the space.
If you plan on using the space for 1 hour, you pay $1. If you plan on using the space for 2 hours, you pay $4. Now, why is this? Shouldn’t you pay $2 for the 2 hours? While 1 hour costs $1, ParkMobile increases the amount due, in relation to the number of hours being used, because it’s inconvenient for a user to extend their rented parking pass every hour on the hour.
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2F70043298-2cd0-4874-afb0-b223b34de3e2%2F079f0af7-c068-4719-8382-d8971b031c69%2FUntitled.png%3Ftable%3Dblock%26id%3D4472f4ec-9ddb-48f8-9595-aefdddd9feed%26spaceId%3D70043298-2cd0-4874-afb0-b223b34de3e2%26expirationTimestamp%3D1725609600000%26signature%3DnmZsXRuzupK_UjyRBRUQe1KmaX92EGYpjbX-4B0S7OQ?table=block&id=4472f4ec-9ddb-48f8-9595-aefdddd9feed&cache=v2)
Problem
Okay, so what’s the problem? I sometimes wake up late; to make sure I’m not late for class, I park at one of these slots and pay every hour on the hour to save money. Well, this doesn’t play out accordingly all the time. There are certain times when I forget to pay on the hour, resulting in getting a parking ticket from the school’s parking services.
Solution
There are a few ways to solve this problem:
- Wake up early so that I don’t have to park at one of the park mobile slots
- Pay for the number of hours I will be using the slot
- Set an alarm every hour on the hour to remind me to renew the park mobile slot
- Create a bot to renew the slot for every hour on the hour
I think the solution to this problem is simple and obvious — create a bot to renew the parking slot every hour on the hour. This should be fun.
Process
Enjoy this quick/beautiful sketch of the workflow I drew on my iPad. Sorry for the bad handwriting (not really).
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2F70043298-2cd0-4874-afb0-b223b34de3e2%2Ff980c6d9-c83f-4707-b6d7-f66188f513f1%2FUntitled.png%3Ftable%3Dblock%26id%3Dc8d6247c-6d3c-4978-8d38-8287823bbfd2%26spaceId%3D70043298-2cd0-4874-afb0-b223b34de3e2%26expirationTimestamp%3D1725609600000%26signature%3DG8jVxpZu6btsjdw9pEgdpt6rx6pN6J_XIMTDr5NIqNU?table=block&id=c8d6247c-6d3c-4978-8d38-8287823bbfd2&cache=v2)
I think the steps are self-explanatory, but I’ll briefly explain the goal of each step in the workflow:
- Login: In order to rent a slot, park mobile requires you to create an account. This account will contain all of a user’s information, such as the vehicle, payment information, etc. The script needs to be able to log in using my account to pay for the slot.
- Select Zone Number: Pretty simple, the script needs to select the parking zone where my car is parked at. This will be hardcoded because I won’t be moving my car at any time.
- Specify Duration: This will be hardcoded to 1 hour (the whole point of this script).
- Select Vehicle: My vehicle is already registered to my account and I am assuming park mobile has a distinct id for it. I need to figure out what it is.
- Add Payment Info: This is already registered to my account as well. I am also assuming that a distinct id exists for the payment information.
- Submit: All the previous steps don’t have to be performed by the script. I mean, it could be if I plan on using a browser library, like Mechanical/Beautiful Soup, but my goal is to simply use requests. One request, including all the information above, should get the job done. This request should be invoked automatically as soon as a session is over.
I am building this as I write this, so hopefully, it goes according to plan.
Login
We need to find the endpoint for logging in. This is pretty easy. On the login page, after we press the Sign In button, we need to monitor the requests that are invoked.
![You can do this by going to Developer Tools → Network.](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2F70043298-2cd0-4874-afb0-b223b34de3e2%2F33210f20-d5a2-403f-94ae-c466516a96be%2FUntitled.png%3Ftable%3Dblock%26id%3D81b4e6a6-4446-4ad1-a67d-96b47b30c426%26spaceId%3D70043298-2cd0-4874-afb0-b223b34de3e2%26expirationTimestamp%3D1725609600000%26signature%3DCFabHTS99KwsThi8ymx2Jo6UdEHqzxzn4MpnZToppB0?table=block&id=81b4e6a6-4446-4ad1-a67d-96b47b30c426&cache=v2)
Cool, we got our endpoint. This is what our request will look like.
/* Need to fetch a xsrf-token. Can easily be done by fetching the home page. */ const res = fetch("https://app.parkmobile.io/login"); const xsrfToken = res.headers["cookies"]["XSRF-TOKEN"]; const res = fetch("https://app.parkmobile.io/api/login", { body: JSON.stringify({email: "...", password: "..."}), headers: { "content-type": "application/json", "origin": "https://app.parkmobile.io", "referer": "https://app.parkmobile.io/", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "sourceappkey": "ParkmobileWeb", "x-xsrf-token": xsrfToken } });
Testing this using any tool will give us a 200 response. Awesome.
![notion image](https://www.notion.so/image/https%3A%2F%2Ffile.notion.so%2Ff%2Ff%2F70043298-2cd0-4874-afb0-b223b34de3e2%2F2b6f668a-f233-4124-a967-26d2d7ec72fe%2FUntitled.jpg%3Ftable%3Dblock%26id%3Dc64bb5c3-ec85-4e5c-86de-106827e22b27%26spaceId%3D70043298-2cd0-4874-afb0-b223b34de3e2%26expirationTimestamp%3D1725609600000%26signature%3D5OL4i7KTr-cSD0ZDF1RFtZ_RQwVdXmHOzoIFj2pdiN8?table=block&id=c64bb5c3-ec85-4e5c-86de-106827e22b27&cache=v2)
Zone Number
#3012 is the zone number we want to reserve.