with one click
boss-auto-job
// BOSS直聘自动求职: Camoufox隐身搜索→多Agent匹配→生成打招呼→自动投递。4层反爬绕过(TLS/行为/网关/风控),AST解密zp_stoken,Code 36/32安全停止机制。
// BOSS直聘自动求职: Camoufox隐身搜索→多Agent匹配→生成打招呼→自动投递。4层反爬绕过(TLS/行为/网关/风控),AST解密zp_stoken,Code 36/32安全停止机制。
| name | boss-auto-job |
| description | BOSS直聘自动求职: Camoufox隐身搜索→多Agent匹配→生成打招呼→自动投递。4层反爬绕过(TLS/行为/网关/风控),AST解密zp_stoken,Code 36/32安全停止机制。 |
General-purpose web platform automation framework demonstrated on BOSS Zhipin. Pattern: login session persistence → data scraping → multi-agent analysis → automated action execution. Adaptable to any web platform requiring cookie-based auth and batch AI processing.
1. Login & Session Persistence
└─ Browser login → Extract cookies → Save to ~/.hermes/credentials/
└─ Subsequent runs: load cookies → validate → refresh if needed
2. Data Scraping
└─ Authenticated requests with persisted cookies
└─ HTML parsing + API fallback strategy
└─ Output structured JSON with delimiters (===JSON_START/END===)
3. Multi-Agent Analysis
└─ Delegate each item to subagent with structured prompt
└─ Parallel scoring/matching/generation
└─ Collect results, filter by threshold
4. Automated Action Execution
└─ Generate browser action sequences (navigate, click, type, verify)
└─ Agent executes via browser_* tools
└─ Rate limiting between actions
~/.hermes/credentials/resume.txt (plain text)requests, beautifulsoup4 installed1. Check/Restore Login
└─ Cookie exists? → Valid? → Proceed / Re-login
2. Search Jobs
└─ Input job name → Search → Scrape JD list
3. Multi-Agent Match
└─ Delegate each JD to subagent → Score 0-100
4. Filter & Rank
└─ Sort by score → Keep top N (default 10)
5. Generate Introductions
└─ Per JD: analyze requirements → generate tailored intro
6. Send Applications
└─ Per target JD: send with generated intro
To adapt this pattern to another platform:
login.py → target platform login pagesearch.py → target platform search API/HTMLmatch.py → your analysis criteriagenerate.py → your output formatsend.py → target platform DOM selectorsFirst run:
python scripts/login.py
~/.hermes/credentials/boss_cookies.jsonSubsequent runs:
Uses Camoufox (C++ level Firefox fingerprint spoofing) to bypass ALL 4 layers of BOSS anti-bot detection.
python scripts/search_camoufox.py "产品经理" --city=101010100 --pages=3
Why Camoufox wins:
Tested result:
普通 Playwright + Cookie → Code 0 (but gets Code 36 after heavy use)
Camoufox without Cookie → Code 0 (passes all 4 layers automatically)
If Camoufox is not installed, use Playwright with user cookies:
python scripts/search_playwright.py "产品经理" 101010100 1
Requires: valid cookies in ~/.agent-browser/auth/boss-zhipin.json
Controls user's real Chrome browser via remote debugging port:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --remote-allow-origins='*'
python scripts/search_chrome_cdp.py "产品经理" --city=101010100 --pages=3
TLS fingerprint bypass without browser:
python scripts/search_curl_cffi.py "产品经理" --city=101010100
Note: curl_cffi bypasses TLS fingerprint but cannot pass behavior detection (code 37).
BOSS renders job cards on <canvas> to prevent DOM scraping. Always use the API (/wapi/zpgeek/search/joblist.json) instead of parsing HTML.
Output format: [ "https://www.zhipin.com/web/geek/job?query=产品经理&city=101010100&page=1", "https://www.zhipin.com/web/geek/job?query=产品经理&city=101010100&page=2" ]
**Agent workflow per URL:**
1. `browser_navigate(url)` — open search page
2. `browser_snapshot(full=true)` — get page HTML
3. Pass HTML to `extract_jobs_from_page()` (built into script)
4. Wait 2-3 seconds between pages
**Output format:**
```json
[
{
"job_id": "123456",
"title": "高级产品经理",
"company": "某某科技",
"salary": "25-40K",
"location": "北京·朝阳区",
"requirements": ["3-5年经验", "本科", "电商经验"],
"jd_text": "负责...",
"boss_name": "张先生",
"boss_title": "HR"
}
]
Use delegate_task with parallel subagents. Each subagent receives:
resume.txtSubagent prompt:
You are a professional HR recruiter. Compare this JD against the candidate's resume.
JD: {jd_text}
Resume: {resume_content}
Score 0-100 based on:
- Skills match (40%)
- Experience relevance (30%)
- Education fit (10%)
- Industry alignment (20%)
Return ONLY JSON: {"score": 85, "reason": "brief explanation"}
Parallel execution (max 3 concurrent — batch accordingly):
# delegate_task maxes at 3 concurrent children
# Batch 10 jobs into 3-4 subagent calls, each scoring 3-4 jobs
tasks = [
{"goal": "Score these 3 jobs", "context": f"JDs: {batch1}\nResume: {resume}", "toolsets": []},
{"goal": "Score these 3 jobs", "context": f"JDs: {batch2}\nResume: {resume}", "toolsets": []},
{"goal": "Score these 4 jobs", "context": f"JDs: {batch3}\nResume: {resume}", "toolsets": []},
]
delegate_task(tasks=tasks)
Collect all scores, sort descending. Default keep top 10.
不再使用固定模板,也不调外部 API。 招呼语由 Agent 自己根据 JD 和简历的内容直接生成。
Agent 就是 LLM,它读取搜索结果中的 JD 信息和简历内容后,直接写出个性化招呼语。 无需额外的 Python 脚本或 API 配置。
1. 搜索结果返回后,Agent 读取每个职位的 title、company、requirements、jd_text
2. 读取 resume.txt
3. 对每个职位,Agent 直接生成个性化招呼语(这一步不需要调任何工具)
4. 用 send_camoufox.py <job_id> "招呼语" 发送
Critical: encryptUserId is NOT returned by the search API.
You must fetch it from the job detail API:
/wapi/zpgeek/job/card.json?encryptJobId={job_id}
Or use search_playwright.py which runs inside a browser context where you can call both APIs.
python scripts/send_v2.py --job-id=123456 --intro="生成的介绍"
boss-auto-job/
SKILL.md # Main docs
REVERSE_ENGINEERING.md # BOSS anti-bot reverse engineering report
BYPASS_SOLUTION.md # Bypass strategy with GitHub projects
scripts/
boss_apply.py # 🎯 One-click pipeline (Camoufox)
search_camoufox.py # 🏆 Search via Camoufox (PRIMARY)
send_camoufox.py # 🏆 Send via Camoufox (PRIMARY)
search_playwright.py # Search via Playwright (legacy)
search_chrome_cdp.py # Search via Chrome CDP (legacy)
search_curl_cffi.py # Search via curl_cffi (legacy)
search_browser.py # Search via browser automation (legacy)
search.py # requests-based search (deprecated)
match.py # Multi-agent matching orchestrator
generate.py # Introduction prompt builder (reference)
send_final.py # Message sender (legacy)
refresh_cookies.py # Cookie refresh tool
login.py # Login helper
orchestrator.py # Full pipeline orchestrator
| Priority | Script | Command | Status |
|---|---|---|---|
| 🥇 | search_camoufox.py | python search_camoufox.py "产品经理" | ✅ Best stealth |
| 🥇 | send_camoufox.py | python send_camoufox.py <job_id> "msg" | ✅ Best stealth |
| 🥇 | boss_apply.py | python boss_apply.py "产品经理" --send | ✅ One-click |
| 🥈 | search_playwright.py | python search_playwright.py "产品经理" 101010100 1 | ⚠️ Legacy |
| 🥉 | search_chrome_cdp.py | python search_chrome_cdp.py "产品经理" | ⚠️ Legacy |
This pattern applies to any web platform using dynamically loaded obfuscated JS for bot detection:
security-js/{name}.js (or equivalent endpoint)window.ABC or similar global constructorwindow, document, navigator, location)Network.setCookie to inject into real browserBOSS security-check uses dynamically named JS files (security-js/{hash}.js) with the following structure:
// IIFE pattern, exposes window.ABC
(function() {
window.md5 = ...
window.s = ...
window.ABC = function() {
this.z = function(seed, ts) {
// Complex string manipulation using md5 + timestamp
// Returns base64-like encoded string (265 chars)
}
}
})();
Key parameters:
seed: Random string from redirect URL (URL-encoded base64)ts: Timestamp from redirect URLname: JS file identifier (e.g., b23b7024)offset: new Date().getTimezoneOffset() (China = -480)parseInt(ts) + 60 * (480 + offset) * 1000Security check page flow:
security-check.htmlsecurity-js/{name}.jswindow.ABC becomes availablenew ABC().z(seed, adjusted_ts) → generates __zp_stoken____zp_stoken__={token}; domain=.zhipin.com; path=/; expires={now+2304e5}callbackUrlWhy requests alone fails:
Even with correct zp_stoken, BOSS detects non-browser TLS fingerprint and missing browser APIs. The token alone is necessary but not sufficient.
Why CDP works:
Chrome CDP controls a real browser instance. When we inject the zp_stoken cookie via Network.setCookie, the browser presents a legitimate environment (correct TLS, canvas, WebGL, etc.), passing all checks.
| Code | Meaning | Action |
|---|---|---|
| 0 | Success | Process job data |
| 37 | Environment abnormal | Auto-generate zp_stoken (see below) |
| 36 | Account flagged | User must manually verify in browser, then run refresh_cookies.py |
| 32 | Account banned temporarily | More severe than 36. Stop all automation. User must manually verify AND send a message in their browser to restore full access. |
| 1006 | Rate limited | Wait 10s and retry |
curl_cffi with impersonate='chrome120' mimics Chrome's TLS/JA3 fingerprint. This alone is enough to pass Layer 2 (environment fingerprinting) — the page loads as 200 instead of 302. However, if the account itself is flagged (code 36), even correct TLS fingerprint won't help. The user must manually verify first.
Tested flow:
curl_cffi.get(page_url, impersonate='chrome120') → 200 ✅ (not 302)curl_cffi.get(api_url, impersonate='chrome120') → code 36 or 37zp_stoken via Node.js VM, inject cookie, retry → code 0 or 36refresh_cookies.py for manual verificationWhen cookies are expired or account is flagged (code 36):
cd ~/.hermes/skills/productivity/boss-auto-job/scripts
python refresh_cookies.py
This opens a visible Chromium window with existing cookies loaded. If verification appears, user completes it manually. Script detects successful login, exports updated cookies to ~/.agent-browser/auth/boss-zhipin.json, and validates the API.
Cookie source file: ~/.agent-browser/auth/boss-zhipin.json (Playwright CDP format with cookies array containing name, value, domain, path, expires, httpOnly, secure fields)
To adapt this bypass pattern to another platform:
<script src="..."> tagsesprima or manual regex to find the global constructorvm.Context with window, document, navigator, locationNetwork.setCookie or browser automationboss_apply.py (Camoufox Edition)cd ~/.hermes/skills/productivity/boss-auto-job/scripts
# 搜索+匹配+生成(不发送)
python boss_apply.py "产品经理"
# 搜索+匹配+生成+发送
python boss_apply.py "产品经理" --send
# 指定城市、页数、Top N
python boss_apply.py "产品经理" --city=101020100 --pages=2 --top=5
# 模拟发送(不实际发消息)
python boss_apply.py "产品经理" --send --dry-run
# 单独搜索
python search_camoufox.py "Python" --city=101010100 --pages=3
# 单独发送
python send_camoufox.py <job_id> "你好,我对这个职位很感兴趣"
# 首次使用 / Cookie 过期时(会自动弹出扫码登录)
python send_camoufox.py <job_id> "你好,我对这个职位很感兴趣"
# → 🔐 未登录或登录已过期,需要重新扫码登录
# → 请用手机 BOSS App 扫描页面上的二维码
# → 登录成功后自动保存 Cookie,下次无需再次扫码
底层引擎: Camoufox (C++级Firefox指纹修改)
pip install "camoufox[geoip]"camoufox fetch (下载~100MB Firefox二进制)登录认证说明:
send_camoufox.py 检测到 Code 17 时自动弹出扫码登录页,用户在 Camoufox 内登录后 Cookie 与指纹一致~/.agent-browser/auth/boss-zhipin.json,后续发送自动复用python boss_apply.py "关键词" --send===SEARCH_RESULT=== 块提取 jobs 列表(含 JD 详情)delegate_task(tasks=batches) 对每批3个职位打分python send_camoufox.py <job_id> "招呼语",间隔 5 秒# 1. 搜索
terminal("cd scripts && python boss_apply.py '产品经理' --send")
# 解析 SEARCH_RESULT 块中的 first_5、jobs_file 等
# 2. 匹配(每批3个,delegate_task max 3 concurrent)
delegate_task(tasks=[
{"goal": "Score these 3 jobs...", "context": "Resume: ...\nJob 1: ...\nJob 2: ...\nJob 3: ...", "toolsets": []},
{"goal": "Score these 3 jobs...", "context": "...", "toolsets": []},
{"goal": "Score these 4 jobs...", "context": "...", "toolsets": []},
])
# 3. 排名+生成招呼语
# 取 score >= 60 的职位,delegate_task 生成打招呼语
# 4. 发送(间隔 3 秒,每次发完检查返回码)
| Code | 含义 | 正确操作 | ❌ 错误操作 |
|---|---|---|---|
| 0 | 成功 | 处理数据 | — |
| 37 | 环境异常 | 自动生成 zp_stoken 重试一次 | 反复重试 |
| 36 | 账户异常 | 立即停止,告诉用户手动验证 | 换脚本重试 |
| 32 | 账户封禁 | 立即停止,告诉用户手动发消息恢复 | 继续搜索 |
1. 停止所有自动化操作
2. 告诉用户:
- Code 36: "BOSS 检测到异常,请在 Chrome 中打开 zhipin.com 完成验证后告诉我"
- Code 32: "BOSS 账户被临时封禁。请:① 在 Chrome 中完成验证 ② 随便找一个职位点'立即沟通'发一条消息"
3. 等待用户确认恢复
4. 确认后用 AppleScript 导出 Cookie:
osascript -e 'tell application "Google Chrome" to tell active tab of front window to return execute javascript "document.cookie"'
5. 合并 Cookie 并保存到 ~/.agent-browser/auth/boss-zhipin.json
6. 再恢复自动化
When the agent encounters code 36 ("您的账户存在异常行为") during any API call:
Never try to auto-solve code 36 — it requires human verification (Geetest CAPTCHA).
Code 32 ("已暂时被禁止使用") is more severe than 36. The user's account is temporarily banned from detail/send APIs.
When refresh_cookies.py can't launch a visible browser (missing Playwright browser install), ask the user to export cookies manually:
Cmd+Option+I → Console tabcopy(JSON.stringify({cookies: document.cookie.split('; ').map(c => {const [n,...v]=c.split('='); return {name:n, value:v.join('='), domain:'.zhipin.com', path:'/', expires:-1, size:v.join('=').length, httpOnly:false, secure:false, session:true};}), origins:[]}, null, 2))
pbpaste > ~/.agent-browser/auth/boss-zhipin.json
Note: This only gets non-HttpOnly cookies. Key cookies (wt2, zp_at, bst) ARE accessible via document.cookie and are sufficient for the search API to work.
AppleScript fallback (when DevTools is blocked): BOSS auto-closes the page when DevTools opens (anti-debug). If user can't open Console, use AppleScript to read cookies directly from their running Chrome:
osascript -e 'tell application "Google Chrome" to tell active tab of front window to return execute javascript "document.cookie"'
This returns all non-HttpOnly cookies as a single string. Parse and save:
raw = "lastCity=101280600; __g=-; bst=xxx; ..."
cookies = {k: v for k, v in (p.split('=', 1) for p in raw.split('; ') if '=' in p)}
# Merge with existing auth file to preserve httpOnly cookies (wt2, zp_at, etc.)
The merged result (fresh non-HttpOnly + stale httpOnly) works for the search API.
Important: After any verification/code-36 recovery, user MUST also send a manual message to any BOSS recruiter in their browser. This signals to BOSS's risk engine that the account is active and human-operated, restoring full API access for detail/send endpoints.
Full reverse engineering analysis: REVERSE_ENGINEERING.md in skill directory.
Full bypass strategy based on GitHub open source research: BYPASS_SOLUTION.md in skill directory.
Recommended approach (ranked):
pip install camoufox) — C++ level fingerprint spoofing, humanize=True, geoip=True, passes all 30+ detection sitespip install cloakbrowser) — Custom Chromium with 49 C++ patches, passes Cloudflare/reCAPTCHA/FingerprintJSpip install rebrowser-playwright) — Drop-in Playwright replacement fixing Runtime.Enable leak + navigator.webdriverKey insight: JS-level fingerprint spoofing (Object.defineProperty) is ALWAYS detectable via toString()/getOwnPropertyDescriptor/Worker context mismatch. C++ level modification (Camoufox/CloakBrowser) is the only truly undetectable approach.
Key findings:
wait_until="networkidle" and increase timeout to 30s for BOSS pagesnetworkidle before evaluating.refresh_cookies.py or ask user to re-export cookies.Camoufox() returns a standard Playwright Browser object, but browser.contexts is an empty list at start. Use browser.new_page() directly — NOT browser.contexts[0].new_page(). The latter throws IndexError: list index out of range.page.goto() in sequence, the second one may fail with TargetClosedError. Fix: create a new page per query with page = browser.new_page() and page.close() after each, instead of reusing one page.wait_until safety: Use wait_until="domcontentloaded" instead of wait_until="networkidle" for BOSS pages. The networkidle timeout is unreliable with BOSS's continuous polling scripts (warlock, patas, heartbeat).refresh_cookies.py to open a visible browser, complete verification manually, script auto-saves new cookiessearch_chrome_cdp.py to control your real Chrome browser (completely bypasses detection){"code": 36, "message": "您的账户存在异常行为"}python refresh_cookies.py → complete verification → cookies auto-exported<canvas> elements to prevent text scraping from the DOM. Even when the page loads successfully, document.querySelectorAll('.job-card') returns empty.
/wapi/zpgeek/search/joblist.json) instead of DOM scraping__zp_stoken__ + correct TLS fingerprintrequests alone will always fail with "您的环境存在异常" (code: 37). Use curl_cffi with chrome120 impersonation or real browser.playwright install chromium requires ~100MB disk space and may fail with ENOSPC. Use Chrome CDP mode instead if disk is tight.send.py selectors may need adjustment after major UI updates.document.cookie returns ~16 cookies (non-HttpOnly). HttpOnly cookies (wt2, zp_at, wbg) must come from the existing auth file. Merge fresh non-HttpOnly + stale HttpOnly cookies for best results.The project also has a standalone CLI (boss) and cross-agent config files:
boss-auto-job/
boss # CLI entry point (chmod +x, Python shebang)
AGENTS.md # Agent-agnostic skill instructions
CLAUDE.md # = AGENTS.md (Claude Code auto-reads)
.cursorrules # = AGENTS.md (Cursor auto-reads)
Usage from any Agent CLI:
./boss search "Agent应用开发" --city 深圳 --area 南山 --match --top 5
./boss search "AI前端" --city 深圳 --match --send
./boss send <job_id> "你好"
GitHub repo: https://github.com/xiarongwen/boss-auto-job
The CLI wraps search_camoufox.py and send_camoufox.py with a unified interface.
AGENTS.md teaches any Agent CLI how to use the boss command.
From testing this pattern:
execute_code may cache old module versions — use subprocess for reliable CLI testing===JSON_START/END===) to avoid regex matching issues with log prefixes like [match].agent-browser/auth/*.json uses Puppeteer/Playwright format with cookies array — convert to requests dict by filtering on domain and extracting name/value pairs__zp_stoken__ can be generated server-side by fetching security-js/{name}.js and executing in Node.js VM. See search_chrome_cdp.py::bypass_security_check() and search_curl_cffi.py::generate_zp_stoken(). However, the token alone is not sufficient — TLS fingerprint must also match.[HINT] Download the complete skill directory including SKILL.md and all related files