DEV Community

member_5d0fa3ad
member_5d0fa3ad

Posted on • Originally published at autoapplymax.com

How I built a Chrome extension that auto-applies to 100 LinkedIn Easy Apply jobs per day

Job hunting on LinkedIn is a numbers game. Median reply rate is 4-8%, so if you want to land 5 offers you probably need to apply to 300+ roles. Filling the same Easy Apply form 300 times is soul-destroying, so 18 months ago I started building a Chrome extension that does it for you.

Today it's called AutoApplyMax — 25K+ users, ~78K API tokens/day of AI form-fill traffic, zero permanent LinkedIn bans on record when users respect the recommended 100-150/day cap.

This post is the postmortem-style writeup of what worked, what broke, and the specific safety rules that keep LinkedIn from banning the bot's users.

The stack

  • Chrome extension (Manifest V3) — content script that lives inside linkedin.com/jobs/*, background service worker for cross-tab coordination
  • Supabase — Postgres + Auth + Edge Functions for the dashboard, profile storage, AI form-fill routing
  • Groq (Llama 3.3 70B) — LLM answering screening questions in <400ms per question, 4 API keys round-robined for rate-limit isolation across free-tier orgs
  • Vercel — hosting the marketing site + dashboard + 100+ blog articles
  • Zero server-side scraping of LinkedIn. Everything runs client-side in the user's own Chrome, using their own logged-in session.

The last point is the load-bearing one for legal + safety reasons. We're not a headless scraper hitting LinkedIn's servers — we're a UI automation running in the user's own browser, driving their own account, at human speed. Same threat model as Bumble's built-in swipe-all bot or any autofill password manager.

The Easy Apply flow, step by step

When the user clicks "Auto-apply" in the extension popup, the content script:

  1. Reads the visible job cards from the .jobs-search-results-list sidebar
  2. For each card, clicks it to open the detail pane (this is a soft nav — no full page load)
  3. Verifies it's Easy Apply by looking for the .jobs-apply-button with data-live-test-easy-apply attribute. If not, skips.
  4. Clicks Easy Apply. LinkedIn opens a modal with the multi-step form.
  5. Walks the form pages. Each page has different fields — name, email, phone, resume upload, custom screening questions.
  6. Fills known fields from the user's profile (stored in the extension's chrome.storage.local)
  7. Uploads resume by creating a File object from the stored blob and dispatching a change event on the <input type="file">
  8. Answers screening questions via Groq — sends the question + user's profile summary, expects a single-line answer that matches the input type (short-text, number, radio)
  9. Clicks Submit, waits for the "Application sent" confirmation, closes the modal
  10. Delays 2-5s randomized, moves to the next card

The pattern is boring on purpose. No fancy async pipelines. No parallel tabs. Just a synchronous walk down the list with realistic delays.

The three safety rules that matter

LinkedIn's ML abuse detection is not looking for "does this account use a bot." It's looking for behavioral signatures. Three rules keep AutoApplyMax users under the radar:

Rule 1 — Never faster than a fast human

Timing between "click Easy Apply" and "click Submit" for a 4-step form: humans do it in 30-90 seconds. AutoApplyMax targets 40-80 seconds. Delays between actions are randomized in a 2000 + Math.random() * 3000 ms window. Never a fixed 500ms. That's the giveaway.

Rule 2 — Daily cap at 100-150

Above 150 applications/day from one account, LinkedIn's Retryable-Errors: LIMIT_EXCEEDED starts showing up on Easy Apply modals. Above 200, temporary restrictions start. So the extension has a hard-coded cap at 150 that the user can lower but not raise. Better to spread across days than push past 150.

Rule 3 — Only automate what belongs to the user

  • Easy Apply on their own account: automated
  • Profile data of other users: never scraped
  • Sending messages, connection requests: never touched
  • Reading job listings: reads what's already visible to the user (their own logged-in search)
  • Public post-view counts, follower lists: never scraped

The line is: the bot can only do things the user themselves can do inside their own logged-in tab. If it would require an unauthenticated crawler or a different account, it's out of scope.

The "form-fill" AI, in one paragraph

The interesting AI work is not "generate a CV." It's answering the ~800 different variations of screening questions LinkedIn shows. "How many years of Python?" "Are you authorized to work in Germany?" "Are you willing to relocate to Bangalore for 6 months?" "What's your notice period in weeks?"

We send the question + a compact JSON summary of the user's profile to Llama 3.3 70B (via Groq for latency — <400ms P95). The system prompt forces a specific output format: {answer: "3", confidence: 0.9} for numeric inputs, {answer: "Yes"} for booleans. Confidence < 0.7 means the bot skips the question (asks the user next session), rather than lie to LinkedIn.

Round-robin across 4 Groq accounts (each with a separate free-tier org) gives us ~400K tokens/day of headroom on llama-3.3-70b-versatile. That's the fun trick: Groq's rate limits are per-org, not per-key, so multiple accounts = multiple TPD pools.

What I got wrong

  • Initial launch: I tried scraping LinkedIn from a server-side headless Chrome. Banned in 2 days. Never do that. Client-side extension is the only sustainable model.
  • Wanted to also automate connection messages. Wrong. Users hated it (spam signal), LinkedIn caught it fast. Now the bot only touches Easy Apply.
  • Sent screening question answers with no confidence check. LLM would confidently lie about years of experience. Now we check confidence and skip when low.
  • Didn't rate-limit early. Users cranked up caps to 500/day. Banned the accounts. Now hard-cap at 150 with no override.

What's next

  • Interview prep AI — feeds recruiter reply text + job description + user's background into an LLM to generate 5 likely questions + STAR-format answers
  • ATS optimization layer — before submitting, the extension checks if the resume ATS-matches the JD keywords, offers to swap in a tailored version generated on-the-fly
  • Multi-account rate-limiting via Supabase RLS — track per-user daily counts server-side so a user can't bypass the cap by clearing extension storage

Try it

If you want to see the extension in action, install AutoApplyMax from the Chrome Web Store (free). No signup needed to start. Or read the full auto-apply guide at autoapplymax.com/blog/how-to-auto-apply-on-linkedin-2026.

Happy to answer any technical questions in the comments — especially interested in stories of other people who built form-filling automations.

Top comments (0)