Open-source project
wodsuz/EasyApplyJobsBot avatar
wodsuz/EasyApplyJobsBot

EasyApplyJobsBot drives LinkedIn Easy Apply in a Selenium container that expects an X display nobody starts

A python bot to automatically apply all Linkedin,Glassdoor, etc Easy Apply jobs based on your preferences. Auto login, auto fill additional questions, apply automatically!

829 stars225 forksPythonNOASSERTION

At a glance

What is it?
A Python Selenium bot that logs into your own account and applies to jobs, with a Docker path that installs Chrome and the full X11 client stack, sets DISPLAY=:99 and then runs the script with no X server running. The page itself has been rebranded into an advertisement for a separate Chrome extension, and the bot's documentation is sold as six paywalled links.
Who is it for?
Read the terms and the security surface before running this, not the feature list. The credentials go into `config.py` on lines 7 and 8 in plaintext, the dependencies include a stealth layer built to avoid bot detection, and job board terms almost always prohibit automated applying, so the risk is to the account you automate rather than to the software.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 147 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The container sets DISPLAY=:99 and nothing in the image starts an X server

The Docker path is the recommended one on this page, and the image it builds has a gap. It installs Google Chrome plus the entire GTK and X11 client library list, sets `ENV DISPLAY=:99`, and its command is `python3 linkedin.py`. There is no Xvfb in the package list, no X server started, and no supervisor or entrypoint script that would start one. So the default run asks for a display on :99 that nothing in the image is providing.

The compose file repeats the same expectation and offers the way out in a comment rather than in the defaults:

yaml
    environment:
      - DISPLAY=:99
    # Uncomment the following lines if you want to run in headless mode by default
    # environment:
    #   - DISPLAY=:99
    #   - HEADLESS=true

Headless is available as a variable and is off by default, and the two commented environment blocks are duplicated, so uncommenting means editing rather than appending. The rest of the compose file is careful: four bind mounts for data, cookies, `config.py` and `additionalQuestions.yaml`, the last two with a comment explaining that mounting them means users can edit them without rebuilding. It also sets `restart: unless-stopped` along with `stdin_open: true` and `tty: true`, and the comment on those says to remove them for detached mode, which is the opposite of what most compose files default to.

Chrome itself is installed the long way, by piping the signing key into gpg, writing a sources list entry and installing the package:

dockerfile
# Install Google Chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /usr/share/keyrings/googlechrome-linux-keyring.gpg \
    && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrome-linux-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
    && apt-get update \
    && apt-get install -y google-chrome-stable \
    && rm -rf /var/lib/apt/lists/*

That sources line pins the architecture to amd64, so the image as written is single-architecture even though nothing in the compose file says so.

The page is now mostly an advertisement for a separate Chrome extension

The first line of the page announces a rebrand, and everything after it sells the new thing. The project moved from automated-bots.com to Apllie.com, and the majority of the page is now a Chrome Web Store listing for a browser extension called Apllie, a Smart Application Tracker. Eight feature bullets follow: centralized application tracking from a dashboard, auto-filling custom questions, analytics with CSV and PDF export, AI resume recommendations, interview preparation, cross platform compatibility, filters with whitelists and blacklists, automated follow ups, and a privacy claim that the extension only accesses pages when you use it and stores data locally.

A limited time offer of 20 free credits on signup sits under that list, and a support email closes it. The repository's declared homepage is the commercial site.

What is left of the bot is a short summary, a rebrand notice, and a feature list of about seven items. Two of those items are labelled PRO, including the one about exporting results and offers to txt and csv, which is odd in a list that is supposed to describe the free version you just cloned. Another explains that unanswered questions can be exported to a txt file, answered by hand, and reused on the next run, which is the mechanism that makes the auto-fill work over time.

Both demo videos are of the Pro version, one on Linux Firefox and one on Linux Chrome. So the visible demonstration is of the paid tier, and the free repository is the unshown one.

The bot's own documentation is sold as six checkout links

The section headed as purchasing additional materials and guides is the longest list of links on the page, and every one is a hosted checkout. Three are one-to-one support calls to install the bot, priced separately for Windows, for Linux and for Mac OS. Three more are the documentation itself, again one per platform. A donation link sits above them, and the text around them describes the alternatives: a full tutorial explaining in depth how the bot works, a one hour booking session where the author builds and runs it on your machine, or five videos.

That is six paid documentation links plus a donation link plus a session plus a video pack, attached to a repository that is free to clone. The dependency of the free tier on the paid tier is stated as a fact: the free version is what you get here, and the pro version is on the site.

The trust surface around that is unusual enough to quote. The page warns that there are forked or similar looking versions of this bot using scam and phishing donation links, tells you to make sure you are on the correct site before purchasing, and asks you to check for a logo on each crypto payment site. A project warning that clones of it are used to run phishing donation pages is telling you something real about how its own distribution channel gets abused, and it is also the reason to treat every payment link above with the same suspicion the page asks you to direct at the forks.

The free version's licence is a condition in prose, not a file

The licensing terms are stated in a sentence rather than in a licence file. The page says this is the free version of the bot and that you can fork and modify it by crediting the authors and without changing the donation links. The spelling of modify is wrong in the original, which is worth noting only because the rest of the feature list carries the same pattern, with avalible, unasnwered twice and a capitalised GLobalLogic.

Those two conditions, credit and unchanged donation links, are not the kind of thing an open source licence expresses, and they sit in tension with one. Alongside them the repository has a LICENSE file at its root, while the licence field recorded for the repository is left unasserted, which is the same value used when nothing can be determined. Nothing on the page says which of the three statements governs, so anyone planning to redistribute this should settle that with the authors rather than assume the file in the root settles it.

The maintenance position is equally thin. There are no published releases, so the page's feature list has no version attached to it, and the last commit is dated 2026-05-18. For a bot that depends on the structure of somebody else's job board pages, a five month old last commit is the fact to weigh before you rely on it.

Four dependencies, one of them built to stop the site seeing a bot

The runtime requirements are four lines:

text
selenium>=4.0.0
webdriver_manager>=3.8.0
selenium-stealth>=1.0.0
pyyaml>=5.1

`webdriver_manager` fetches the browser driver at run time rather than shipping one, which is convenient and means the first run reaches the network for a binary. `selenium-stealth` is the entry that matters for understanding what this tool is doing: its purpose is to make an automated session harder to distinguish from a manual one. That is the honest characterisation of a bot built around it, and it is also the reason to read the terms of any job board before pointing it at one.

`pyyaml` is there for `additionalQuestions.yaml` and `requirements.yaml`. That second file is the odd one: it sits in the tree next to `requirements.txt`, and the Dockerfile copies only `requirements.txt`, so nothing in the shipped image reads the YAML one. The tree is otherwise small and flat, with `linkedin.py` as the entry point the Dockerfile invokes, plus `config.py`, `constants.py` and `utils.py`, all brought in by a single wildcard copy.

There is no test directory and no workflows directory in the tree, so nothing here runs a check on push. And the configuration step in the install instructions is explicit that `config.py` is where your LinkedIn email and password go, on lines 7 and 8, in a file that gets copied into the image and then bind mounted back over it.

The page names seven job sites and the tree carries one module

The bot's own feature list says it can be used for many job search websites, and then lists them: Linkedin, Glassdoor, AngelCo, Greenhouse, Monster, GLobalLogic and Djinni. A second list appears higher up for the Chrome extension rather than the bot, with a different set again, covering LinkedIn, Indeed, Glassdoor, Monster, Meta and ZipRecruiter. Two adjacent lists with two different sets of sites is a lot of overlap for readers who assume they describe the same thing.

What the repository contains does not match either list. There is `linkedin.py` and nothing that is named for any of the other six, so the multi-site claim is not backed by per-site modules in this tree. That is consistent with the demo videos both being LinkedIn shaped, and with the entry point being a single LinkedIn script, but it means the claim as written overstates what is here.

The remaining documented behaviour is narrower and more useful. There are two ways to run: with a password, or in a mode the page describes as fully secure with no credentials stored. Job preferences are described as fully customizable, with advanced filters and search filters. Unanswered application questions can be exported to a txt file, filled in, and reused on the next run. Those four are the mechanics, and each one is something you would want to understand before pointing an unattended browser at your own account.

Editorial conclusion

Read the terms and the security surface before running this, not the feature list. The credentials go into `config.py` on lines 7 and 8 in plaintext, the dependencies include a stealth layer built to avoid bot detection, and job board terms almost always prohibit automated applying, so the risk is to the account you automate rather than to the software. The Docker path also needs work before it will run: the image sets a display and installs a browser but starts no X server, and there is no `HEADLESS` default. On the project itself, the honest read is that this is the free stub of a commercial product. The page has been rebranded to sell a Chrome extension, the demo videos show the paid tier, the documentation for all three platforms is sold separately, and the authors themselves warn that scam forks of it are circulating with phishing donation links. The last commit is dated 2026-05-18 and there are no releases, so pin nothing and expect the site selectors to need editing.

Frequently asked questions

Does EasyApplyJobsBot store my LinkedIn password?

The install instructions say to put your LinkedIn email and password into `config.py` on lines 7 and 8, in plaintext, and the Dockerfile both copies that file into the image and bind mounts it back over the copy. The page also describes a second option, a mode with no credentials stored, as fully secure. The compose file mounts a `./cookies` directory to persist login sessions.

Will the EasyApplyJobsBot Docker image start on its own?

Not as written. The image installs Google Chrome and the X11 client libraries, sets `ENV DISPLAY=:99`, and runs `python3 linkedin.py`, but the package list contains no Xvfb and no X server is started. Headless is available as a `HEADLESS=true` variable in the compose file and is commented out by default.

What Python packages does EasyApplyJobsBot need?

Four: `selenium`, `webdriver_manager`, `selenium-stealth` and `pyyaml`. The driver is fetched at run time by `webdriver_manager` rather than shipped in the image, and `selenium-stealth` is the layer that makes an automated session harder to tell apart from a manual one.

Is EasyApplyJobsBot free, and where is the source of the paid version?

The repository is the free version, and the page directs the pro version to the project's own commercial site, which is also the repository's declared homepage. Documentation for Windows, Linux and Mac OS is sold as three separate links, and one-to-one installation support is sold as three more. The page also says forked copies of the bot are being used with scam donation links.

How does EasyApplyJobsBot handle application questions it cannot answer?

It exports the unanswered questions to a txt file, you fill in the answers there, and the bot uses those values on the next run. Answering them automatically with AI is listed separately and marked as a pro feature, so the free version's loop is export, edit, reuse.

Official sources

  1. Issues
  2. Project website
  3. README
  4. wodsuz/EasyApplyJobsBot on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/wodsuz-easyapplyjobsbot.svg)](https://hysenlabs.com/projects/wodsuz-easyapplyjobsbot)