Install
openclaw skills install linkedin-easy-apply-automationAutomate LinkedIn Easy Apply searches and applications with Puppeteer/Chromium, a verified resume PDF, remote/job-title filtering, stateful daily reruns, and...
openclaw skills install linkedin-easy-apply-automationThis skill helps an AI coding/operations agent build and run a repeatable LinkedIn Easy Apply workflow.
It is intentionally public and credential-free. It contains no usernames, passwords, cookies, private profile paths, or user-specific secrets.
RESUME_PDF=/absolute/path/to/resume.pdf
CHROME_PROFILE=$HOME/.cache/linkedin-chrome
STATE_DIR=/tmp/linkedin-easyapply-daily
MAX_SCAN=80
MAX_APPLY=10
DRY_RUN=1
SEARCHES='Claude|OpenAI|Codex|LLM engineer|AI engineer|full stack engineer|software engineer'
LOCATION='United States'
REMOTE_ONLY=1
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({
headless: false,
executablePath: process.env.CHROME_BIN || '/snap/bin/chromium',
userDataDir: process.env.CHROME_PROFILE || `${process.env.HOME}/.cache/linkedin-chrome`,
defaultViewport: null,
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--start-maximized']
});
const page = await browser.newPage();
page.setDefaultTimeout(30000);
page.on('dialog', async d => {
try {
if (d.type() === 'beforeunload') await d.accept();
else await d.dismiss();
} catch {}
});
Build LinkedIn Jobs URLs using explicit filters:
f_AL=true for Easy Apply.United States when requested.Keep candidates only when the card/page supports the requested constraints and the title/description matches the target role family.
When a LinkedIn job ID is known, try the direct flow first:
const applyUrl = `https://www.linkedin.com/jobs/view/${jobId}/apply/?openSDUIApplyFlow=true`;
await page.goto(applyUrl, { waitUntil: 'domcontentloaded', timeout: 60000 });
If the modal does not open, fall back to clicking visible Easy Apply controls across buttons and links.
Answer only facts that are verified by the resume, profile, or explicit operator instruction:
Skip:
Next, Review, then Submit application only when no unknown required fields remain.{
"seen": {},
"applied": {},
"skipped": {},
"alreadySubmitted": {}
}
Write state and logs to:
/tmp/linkedin-easyapply-daily/state.json
/tmp/linkedin-easyapply-daily/results.jsonl
Report concise results:
Submitted:
- Title — Company — URL
Skipped:
- Title — Company — URL — reason
State: /tmp/linkedin-easyapply-daily/state.json
Log: /tmp/linkedin-easyapply-daily/results.jsonl
United States or comfortable as approval.