Skip to content
Conduit

mcp server

jobdrop

28-source job scraper library + MCP server

kbwhodat/jobdropcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "jobdrop": {
      "command": "uvx",
      "args": [
        "jobdrop"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 22, 2026

jobdrop

A multi-source job scraper. Hits 33 job boards in one call, normalizes the results into a pandas DataFrame, and ships with anti-bot handling for the boards that block standard scrapers.

Maintainer: this project is maintained by kbwhodat. Substantially extended from the original cullenwatson/JobSpy (MIT licensed) with new sources, an integrated MCP server, salary/seniority filters, and reliability fixes across all scrapers.

What's in here

33 sources

site_nameSourceNotes
linkedinLinkedInPublic listings + optional detail-page enrichment
indeedIndeedGraphQL with per-company cap + paginate-until-quota
glassdoorGlassdoorListings + company reviews + salary data
googleGoogle JobsSERP aggregation across many sources
zip_recruiterZipRecruiterUS/Canada-focused
hiring_cafeHiring CafeAI-curated, ~140 jobs/page with rich tags (seniority, comp, skills, workplace_type)
wellfoundWellfound (formerly AngelList)50k+ startup roles
collab_workCollabWorkCommunity/newsletter aggregator (~2k curated roles, fastest source)
trueupTrueUpTech-startup curated. Adds company-trajectory score, valuation, funding stage, layoff/health flags. Pure HTTP, sub-second
greenhouseGreenhouse-hosted boardsMost YC and Series A+ companies; 3-layer staleness filter
ashbyAshby-hosted boardsOpenAI, Notion, Linear, Ramp, Mercury, Vercel, etc. Google-dorked discovery + GraphQL enrichment
workdayWorkday tenantsFortune-500-heavy (NVIDIA, Salesforce, Disney, Comcast, JPMorgan, Lockheed, etc.). Google-dorked discovery + CXS API enrichment
leverLever-hosted boardsPlaid, HashiCorp, Kraken, Spotify, etc. Google-dorked discovery + REST enrichment
remoteokRemoteOKFully-remote jobs aggregator. Single global JSON feed, sub-second response
weworkremotelyWeWorkRemotelyFully-remote jobs aggregator. Public RSS feed, currently-live postings only
governmentjobsGovernmentJobs.com (NEOGOV)State/county/city public-sector jobs (non-federal companion to USAJobs). Google-dorked discovery + JSON-LD enrichment
builtinBuilt InTech-vetted local job board family (Built In NYC/LA/Chicago/Atlanta/etc.). Cross-source dedup keeps the tech-quality filter without inflating result count
icimsiCIMSMulti-tenant ATS (~40+ live tenants per query: Sargent & Lundy, Emory, RS&H, VHB, Constructconnect, etc.). Google-dorked discovery + per-tenant HTML enrichment
baytBaytMiddle East focused
naukriNaukriIndia's largest job portal
usajobsUSAJobs.govUS federal public API
adzunaAdzunaPublic API, 100% salary fill rate
joobleJooblePublic API, 60+ countries
findworkFindwork.devDeveloper-focused public API
the_museThe MuseCulture-forward public API
insight_globalInsight Global staffingServer-rendered listings
clearance_jobsClearanceJobs (DHI)Security-cleared roles, full JD + salary + structured job_type
kforceKforce staffingDirect backend API for fast results
snagajobSnagajobDominant US hourly / part-time / shift-work board. Retail, food, warehouse, caregiving. Clean public JSON API
diceDice (DHI)US tech / IT specialty board. SSR'd HTML scrape via Googlebot UA
idealistIdealistLargest US nonprofit / NGO / mission-driven job board. Sitemap-driven + JSON-LD on every detail page
careerbuilderCareerBuilderBroad US/CA general-purpose board. SSR'd HTML with inline jobResults JSON (50 jobs/page). Bypasses Cloudflare WAF via Safari iOS TLS fingerprint
handshakeHandshakeEarly-talent / student / new-grad. Public city-page surface + JSON-LD detail. Most postings auth-walled to verified students; this covers the public slice

Installation

As a Python library

pip install -U jobdrop

Python ≥ 3.10 required.

As an MCP server (Claude Desktop / Claude Code / Cursor / Cline / opencode)

Install the binary once with uv tool install (or pipx install):

uv tool install "jobdrop[mcp]"
# or:  pipx install "jobdrop[mcp]"

Then add to your MCP client config.

Claude Desktop / Claude Code / Cursor / Cline — ~/Library/Application Support/Claude/claude_desktop_config.json (or equivalent):

{
  "mcpServers": {
    "jobdrop": {
      "command": "jobdrop-mcp-server"
    }
  }
}

opencode — ~/.config/opencode/opencode.json (or .opencode/opencode.json in your project):

{
  "mcp": {
    "jobdrop": {
      "type": "local",
      "command": ["jobdrop-mcp-server"],
      "enabled": true
    }
  }
}

That's it — the client launches jobdrop-mcp-server as a stdio subprocess on demand. No daemon, no port.

Note: prefer the uv tool install path so the binary lands in PATH and the client launches it directly — same pattern as reference MCP servers (filesystem, git, etc.).

Usage

from jobdrop import scrape_jobs

jobs = scrape_jobs(
    site_name=["insight_global", "clearance_jobs", "kforce", "greenhouse",
               "linkedin", "indeed", "google"],
    search_term="site reliability engineer",
    location="Atlanta, GA",
    results_wanted=20,
    hours_old=720,          # 30-day freshness cap
    country_indeed="usa",
)
print(f"Found {len(jobs)} jobs")
print(jobs[["site", "title", "company", "location", "min_amount", "max_amount", "job_url"]].head())

Parameters

scrape_jobs(
  site_name              list[str] | str — any of the 28 sources above (default: all)
  search_term            str        — keyword query
  google_search_term     str        — Google Jobs override (only filter for `google`)
  location               str        — "City, ST" or ZIP. Each scraper geocodes its own way.
  distance               int        — radius miles, default 50
  is_remote              bool       — remote-only filter (where supported)
  job_type               str        — "fulltime" | "parttime" | "contract" | "internship"
  easy_apply             bool       — direct-board apply only (where supported)
  results_wanted         int        — per-site target
  offset                 int        — pagination offset
  hours_old              int        — drop postings older than N hours
  country_indeed         str        — Indeed/Glassdoor country (see list below)
  description_format     str        — "markdown" | "html"
  enforce_annual_salary  bool       — convert hourly/monthly to yearly
  linkedin_fetch_description  bool  — full JD + direct URL (slower)
  linkedin_company_ids   list[int]  — filter LinkedIn by company IDs
  proxies                list[str]  — round-robin proxies, "user:pass@host:port"
  ca_cert                str        — CA cert path for proxies
  user_agent             str        — override the default UA
  verbose                int        — 0 errors / 1 warnings / 2 all
)

Per-scraper limitations

  • Indeed — only one of hours_old / (job_type+is_remote) / easy_apply per call.
  • LinkedIn — only one of hours_old / easy_apply per call.
  • ClearanceJobs — location/remote filters require facet IDs from the dropdown endpoints (not implemented). Filter client-side or scope by keyword.
  • InsightGlobal — does not expose client-company name (it's the staffing firm). is_remote is not available in their data.
  • Greenhouse — Google indexes some postings after they're filled. Stale 404s are filtered out; the freshness cutoff filters "live but ancient" postings (default 90 days, override with hours_old).

JobPost schema

JobPost
├── id, title, company_name, company_url, job_url
├── location { country, city, state }
├── description
├── is_remote
├── date_posted
├── job_type        fulltime | parttime | contract | internship
├── compensation
│   ├── interval   yearly | monthly | weekly | daily | hourly
│   ├── min_amount, max_amount, currency
│   └── salary_source
├── job_level                                  (LinkedIn, ClearanceJobs)
├── company_industry                           (LinkedIn, Indeed, Greenhouse, Kforce)
├── company_country, company_addresses,
│   company_employees_label, company_revenue_label,
│   company_description, company_logo          (Indeed)
├── skills, experience_range,
│   company_rating, company_reviews_count,
│   vacancy_count, work_from_home_type         (Naukri)
└── emails

Indeed / Glassdoor country list

Pass country_indeed (use the exact name; * = also supported on Glassdoor):

ArgentinaAustralia*Austria*Bahrain
Belgium*Brazil*Canada*Chile
ChinaColombiaCosta RicaCzech Republic
DenmarkEcuadorEgyptFinland
France*Germany*GreeceHong Kong*
HungaryIndia*IndonesiaIreland*
IsraelItaly*JapanKuwait
LuxembourgMalaysiaMexico*Morocco
Netherlands*New Zealand*NigeriaNorway
OmanPakistanPanamaPeru
PhilippinesPolandPortugalQatar
RomaniaSaudi ArabiaSingapore*South Africa
South KoreaSpain*SwedenSwitzerland*
TaiwanThailandTurkeyUkraine
United Arab EmiratesUK*USA*Uruguay
VenezuelaVietnam*

LinkedIn searches globally and uses only location. ZipRecruiter is US/Canada and uses only location. Bayt searches internationally with only search_term.

Notes

  • Most boards cap a single search at ~1000 results.
  • LinkedIn rate-limits aggressively around the 10th page of pagination on a single IP. Use proxies.
  • For Indeed search-term tuning: it searches the description too. Use -foo to exclude, "exact phrase" for exact match. Example:
    search_term='"site reliability engineer" (kubernetes OR terraform) -recruiter'
    
  • For Google: copy the exact filter syntax from a real Google Jobs search and pass it as google_search_term.
  • For Greenhouse: keyword + location are passed straight to a Google site:greenhouse.io query, so Boolean operators and quotes work. Don't quote the full "City, ST" — quote the city alone, leave the state bare.

License

MIT. See LICENSE.

↑↓ navigate openesc close