01 Sept 2022 · 8 min read

Automating LinkedIn Easy Apply with Python and Selenium

This isn't a claim that spraying applications is the right job-search strategy. It's a claim that if you have decided to play the numbers game, a human should not be the one clicking the buttons.

Defining the search

Everything starts with the search URL. LinkedIn encodes every filter into query parameters, so you build the search you want in the UI - remote, data or growth roles, Easy Apply only, the right seniority - and then hand that URL to the script. No filtering logic needed in code.

Driving the browser

Selenium for interaction, BeautifulSoup for parsing, webdriver_manager to keep the chromedriver in step with the installed Chrome version, and time.sleep between actions so you're not hammering the page.

from bs4 import BeautifulSoup
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import time

options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(ChromeDriverManager().install(), chrome_options=options)
Chrome application tab showing the LinkedIn session cookies, with values redacted
The session lives in a cookie. Reusing it beats re-authenticating on every run - and it is the single most sensitive thing the script touches.

Authentication, then the loop

Log in once by filling the email and password fields and submitting. Then iterate the result pages: open each job card, look for the Easy Apply button, click through the modal, and submit when the form has no unexpected required fields.

That last condition is where all the real complexity lives. Easy Apply is only easy when the form is the default one. The moment a posting adds custom questions - years of experience, salary expectation, a free-text prompt - the script should stop and leave it for a human rather than submit something wrong. Detecting 'this form is not the standard form' is most of the code.

What I'd change

Everything here is fragile by construction. It depends on DOM structure that changes without warning, and browser automation against a logged-in session is exactly the kind of thing platforms actively discourage. It worked, it taught me a lot about resilient selectors, and it's the reason I now reach for a documented API long before I reach for a webdriver.

Share this

← All writing