AI/ML Jobs Scraper - Greenhouse, Lever, Ashby avatar

AI/ML Jobs Scraper - Greenhouse, Lever, Ashby

Pricing

from $2.00 / 1,000 validated results

Go to Apify Store
AI/ML Jobs Scraper - Greenhouse, Lever, Ashby

AI/ML Jobs Scraper - Greenhouse, Lever, Ashby

Scrape AI, ML and data job postings from public Greenhouse, Lever and Ashby boards. Every result is validated, deduplicated and tagged AI-core vs. AI-mention, with a stable versioned schema and built-in source-change monitoring. Also callable from Claude/Cursor via the Apify MCP server.

Pricing

from $2.00 / 1,000 validated results

Rating

0.0

(0)

Developer

Tuyen Tran

Tuyen Tran

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 hours ago

Last modified

Categories

Share

Validated AI, ML and data job postings from public ATS boards — Greenhouse, Lever and Ashby — delivered as a clean, stable, versioned dataset.

What does AI Jobs Daily do?

AI Jobs Daily collects AI, machine-learning and data job postings straight from public applicant tracking system (ATS) boards and turns them into analysis-ready records. Every posting passes a validation gate before it reaches the dataset, is deduplicated across boards, and is tagged so you can separate true AI roles from roles that only mention AI.

It is built for recruiters, hiring-market analysts, job-board operators and AI agents that need a reliable stream of hiring data instead of raw scraped HTML.

Why use this AI jobs scraper?

  • 🎯 AI-core vs. AI-mention classification — ai_core and mentions_ai flags plus an ai_skills list (llm, rag, pytorch...), so you can buy exactly the signal you need.
  • ✅ Validated results only — a strict validation gate runs on every row; invalid postings and partially broken boards never ship to the dataset.
  • 🧩 One schema, many boards — Greenhouse, Lever and Ashby (plus experimental Workable) behind a single, stable, versioned schema. Field names change only with a version bump.
  • 📅 Built for daily feeds — schedule it on Apify, call it via the Apify API, or wire it into Make, Zapier or n8n. Runs come with the full Apify platform: monitoring, scheduling, integrations and export to JSON, CSV or Excel.
  • 🩺 Self-monitoring — every run tracks per-board field fill rates; if a source starts silently losing fields, the run log raises an alarm.
  • 🔒 Public data only — no login walls, no personal data (no names, emails or phone numbers), no proxies required.

Hiring Intent Signals — for Recruiters & GTM Teams

This feed is not a job board. It is a hiring-pressure monitor for recruiters, headhunters and GTM teams.

  • Stuck senior searches — Senior or Staff roles above $200k that have been open 35–55 days (days_open), or were just reposted (is_reposted: true), are signals that the company's own pipeline is not converting. These are accounts worth a headhunting outreach (typical fee: 20–25% of annual salary).
  • Where the budget is going — ai_skills and the number of open roles per company show which stacks they are scaling (vLLM, Ray, Kubernetes, ...), so you can time outreach to the hiring wave instead of guessing.
  • Daily and queryable — schedule the Actor or pull it through the Apify API, Make, Zapier or n8n to keep a live list of accounts with rising hiring pressure.

n8n workflow template: AI Hiring Signal Feed — daily hiring signals from 60 AI companies to Telegram.

How to use AI Jobs Daily

  1. Create a free Apify account — new accounts include monthly usage credits.
  2. Open this Actor and keep the default input (a seeded list of AI-heavy boards) or paste your own company list.
  3. Press Start and wait — a full default run across the 60-board seed list takes about two minutes.
  4. Take the results from the Output tab, or pull them via the Apify API.

AI Jobs Daily input in Apify Console

The Actor input in Apify Console — the defaults are ready to run.

Integrations — use from Claude Desktop, Cursor, or any MCP client

Connect this Actor to any MCP (Model Context Protocol) client through the Apify MCP server, and your AI assistant can query the job feed directly — no glue code.

Option A — local MCP server (stdio):

{
"mcpServers": {
"apify-ai-jobs": {
"command": "npx",
"args": ["-y", "@apify/actors-mcp-server", "--tools", "kotaro001/ai-jobs-daily"],
"env": { "APIFY_TOKEN": "YOUR_APIFY_TOKEN" }
}
}
}

Option B — hosted MCP server (streamable HTTP, no local process):

Point your client at https://mcp.apify.com?tools=kotaro001/ai-jobs-daily and send your Apify token in an Authorization: Bearer <token> header.

Both options expose this Actor as a tool, plus small helpers to fetch run results — and no actor discovery or generic calling tools — so the agent interface stays stable across server updates.

Then ask your agent, for example:

"Find active AI-core ML Engineer jobs in the US with salary floor above $200k, and flag any that look like ghost postings."

Your agent will call this Actor and work with the structured results (title, company, comp_min_usd / comp_max_usd, seniority, workplace_type, visa_sponsorship, ai_core, is_ghost_job, is_reposted, first_seen / last_seen).

Input

FieldTypeDefaultDescription
companiesarray[]Company boards to scrape; leave empty to use the built-in seed list. Each item is either {name, ats, slug} or a domain / careers URL string — e.g. openai.com or https://anthropic.com — auto-detected across Ashby, Greenhouse, Lever and Workable.
max_companiesinteger0Cap how many companies to process — handy for cheap test runs. 0 means no cap.
only_ai_corebooleantrueWhen true, only AI-core jobs are returned. Set to false to also include jobs that merely mention AI.
runModestringdaily_activeWhat goes into the dataset: daily_active — today's validated jobs (default); lifecycle_changes_only — only jobs first seen today plus jobs that just disappeared; full_history_dump — the full lifecycle history kept in your account. See Run modes below.

Example input:

{
"companies": [
{ "name": "OpenAI", "ats": "ashby", "slug": "openai" },
"stripe.com"
],
"max_companies": 10,
"only_ai_core": true,
"runMode": "daily_active"
}

Output

Each dataset item is one validated job posting with 29 core fields: identity (job_id, title, company, plus company_domain and company_linkedin_url — resolved from a static map of the 60 seed companies; the domain is null when the company is unknown, and the LinkedIn URL falls back to a slug derived from the company name, ats, url), location (location_raw, location_city, location_country, workplace_type — remote / hybrid / onsite, null when unclear; country_codes — ISO-3166 alpha-2 codes such as ["US","GB"], empty when unclear; remote_policy stays as the legacy alias), timing (posted_date, first_seen_at, last_seen_at), details (department, employment_type, description_text), salary (salary_raw, comp_min_usd, comp_max_usd — whole-dollar annual USD; EUR/GBP converted via a static rate table shipped with the Actor, hourly rates ×2080, monthly rates ×12; other currencies left empty), seniority (intern / junior / mid / senior / staff / lead; empty when no rule matches), and the AI signal (ai_core, mentions_ai, ai_skills), plus visa_sponsorship — a text-scan heuristic (true when the posting advertises visa sponsorship / H1B transfer / relocation or immigration support; false when it cannot sponsor or requires US citizenship / Green Card / ITAR; null when the text says nothing; a hint, not a verdict). Nine lifecycle fields ride along on every row — stable_id, first_seen, last_seen, lifecycle_status, original_first_seen, repost_count, is_reposted, plus days_open (whole days from first_seen to last_seen) and is_ghost_job — a reference flag (heuristic). Reposts keep their original first_seen, so days_open and is_ghost_job always reflect the true age; see Run modes below. A dataset schema comes with the Actor, with an overview view in the Output tab.

Daily archive (named dataset). Every run also appends its full result set to the named dataset ai-jobs-daily-archive, with a snapshot_date field (YYYY-MM-DD) on every row. Filter on snapshot_date to isolate one day's snapshot. Archive writes are not billed as pay-per-event results, and an archive failure is logged as a warning without failing the run.

Example item (real output, description trimmed):

{
"schema_version": "1.6.0",
"job_id": "a01fc9ed-de08-4326-9206-4ee3f08000dc",
"title": "Machine Learning Engineer, Implicit Signals",
"company": "OpenAI",
"company_domain": "openai.com",
"company_linkedin_url": "https://www.linkedin.com/company/openai",
"ats": "ashby",
"url": "https://jobs.ashbyhq.com/openai/a01fc9ed-de08-4326-9206-4ee3f08000dc",
"location_raw": "San Francisco",
"location_city": "",
"location_country": "",
"remote_policy": "hybrid",
"workplace_type": "hybrid",
"country_codes": ["US"],
"visa_sponsorship": null,
"posted_date": "2026-10-13",
"employment_type": "FullTime",
"department": "Applied AI",
"description_text": "About the Team\nOur team builds classification and evaluation systems that give post-training and research teams fast, reliable feedback on model behavior. ... [trimmed]",
"salary_raw": "$381K – $510K • Offers Equity",
"comp_min_usd": 381000,
"comp_max_usd": 510000,
"seniority": null,
"ai_core": true,
"mentions_ai": true,
"ai_skills": ["distillation", "fine-tuning"],
"status": "open",
"first_seen_at": "2026-10-14T07:45:46Z",
"last_seen_at": "2026-10-14T07:45:46Z",
"stable_id": "8b265edbc3ad521a",
"first_seen": "2026-10-14",
"last_seen": "2026-10-14",
"lifecycle_status": "active",
"days_open": 0,
"is_ghost_job": false,
"original_first_seen": "2026-10-14",
"repost_count": 0,
"is_reposted": false
}

Example item — compact output:

With compactOutputForMcp: true every structured field is kept, but description_text is omitted — here is one real row from a live run (row count and billing are unchanged):

{
"schema_version": "1.6.0",
"job_id": "5f43b884-459e-4a5f-b57c-2c20d48dcbc0",
"title": "Principal Machine Learning Engineer, 3D Geometric Vision",
"company": "Wayve",
"company_domain": "wayve.ai",
"company_linkedin_url": "https://www.linkedin.com/company/wayve",
"ats": "ashby",
"url": "https://jobs.ashbyhq.com/wayve/5f43b884-459e-4a5f-b57c-2c20d48dcbc0",
"location_raw": "Sunnyvale, California USA",
"location_city": "",
"location_country": "",
"remote_policy": "hybrid",
"workplace_type": "hybrid",
"country_codes": ["US"],
"visa_sponsorship": true,
"posted_date": "2026-10-05",
"employment_type": "FullTime",
"department": "AV Engineering",
"salary_raw": "$370,040 – $419,800",
"comp_min_usd": 370040,
"comp_max_usd": 419800,
"seniority": "staff",
"ai_core": true,
"mentions_ai": true,
"ai_skills": ["pytorch", "rag"],
"status": "open",
"first_seen_at": "2026-10-15T11:11:01Z",
"last_seen_at": "2026-10-15T11:11:01Z",
"stable_id": "d729796a56529a6e",
"first_seen": "2026-10-15",
"last_seen": "2026-10-15",
"lifecycle_status": "active",
"days_open": 0,
"is_ghost_job": false,
"original_first_seen": "2026-10-15",
"repost_count": 0,
"is_reposted": false
}

The Sample output tab on this Actor's page shows a full sample dataset — 122 jobs captured from 5 boards in a single run.

AI Jobs Daily output in Apify Console

A full run's dataset in the Console Output tab — one row per validated posting.

Run modes and job lifecycle

Every job carries a stable id and a lifecycle: the first day it was seen (first_seen), the last day it was seen on its board (last_seen) and a status — active or removed. Removed jobs are kept as tombstones, so a posting that returns later keeps its original first_seen. Rows also carry two derived fields: days_open (whole days from first_seen to last_seen) and is_ghost_job — a reference flag (heuristic): it is true only for postings that are still active AND have been open for more than 60 days, which often means a stale or evergreen listing. Treat it as a hint, not a verdict. Three more fields track reposts: original_first_seen (the day the posting first appeared — kept across reposts), repost_count and is_reposted. A repost is a new listing whose content fingerprint — company + normalized title + location + skills + salary band — matches a removed listing of the same company from the last 30 days; the new listing inherits the original first_seen. Detection is deliberately conservative: a missed repost is preferred over a wrong merge.

Your first run is never blind: at the start of every run the Actor fetches the shared public lifecycle map (a key-value record readable without any account) and uses it as a baseline. A job first seen weeks before your run still carries its true first_seen instead of looking brand new. If that fetch fails for any reason, the run simply continues without the map — it can never break your run.

runMode decides what lands in the dataset:

  • daily_active (default) — today's validated jobs, each enriched with its lifecycle fields. The classic daily snapshot.
  • lifecycle_changes_only — only jobs first seen today plus jobs that just disappeared from their boards. Perfect for change alerts and cheap monitoring.
  • full_history_dump — every lifecycle record kept in your account: active jobs plus removed tombstones. You pay per row returned.

Change feed only:

{
"companies": [],
"runMode": "lifecycle_changes_only"
}

One-off full history export:

{
"companies": [],
"runMode": "full_history_dump"
}

Pricing

AI Jobs Daily uses pay-per-event pricing — you pay for validated results, nothing else.

  • From $2.00 to $2.50 per 1,000 validated jobs — the exact rate depends on your Apify subscription plan (per 1,000 results: Free $2.50 / Starter $2.30 / Scale $2.10 / Business $2.00). Each validated dataset row bills one event.
  • Small Actor-start fee — from $0.00002 per event, depending on plan and allocated memory (one event per GB; about $0.0002 per run at the default 4 GB on the Free plan, less on paid plans).
  • Invalid rows and broken boards are never written to the dataset, so you never pay for them.
  • You only pay the events above — there is no additional platform-usage charge.
  • With lifecycle_changes_only a typical daily run costs a fraction of a cent (a handful of events); full_history_dump charges one event per history row returned.

Quick math (Free-plan rate): 100 validated jobs → $0.25; 1,000 → $2.50; 10,000 → $25.00. On paid plans the same runs cost up to 20% less. You can cap the maximum spend per run in Apify Console; the Actor respects the cap and stops cleanly when it is reached.

Reliability and self-healing

Public job boards change their APIs and layouts without notice. AI Jobs Daily is built to notice:

  • A fetch error or a validation-failure spike on a board skips that board for the run — zero partial rows — and records an incident for maintenance.
  • Per-board field fill rates are computed on every run; a field that used to fill more than 50% of rows and drops below 10% triggers a warning in the run log.
  • The classifier is rules-based and deterministic, so results are reproducible run after run.

FAQ

Which companies can I scrape?

Any company with a public Greenhouse, Lever or Ashby board — add it through the input in seconds, no code required. Workable boards are supported experimentally.

How many jobs do I get per run?

It depends on your company list. The default seed list — 60 AI-heavy boards — returns around 690 AI-core jobs per run; smaller subsets scale down from there.

Are only AI roles included?

By default yes (only_ai_core: true). Set it to false to also get jobs that merely mention AI — the ai_core and mentions_ai flags let you filter either way.

How often should I run it?

Daily is a good fit for a hiring-market feed. Runs are deduplicated, so frequent runs only add new postings.

Where does the data come from?

Only public, official application boards. No logins, no personal data, no scraping of private profiles.

Can I trust first_seen from my very first run?

Yes. The Actor ships with a shared public lifecycle map built from its full tracking history, so even on your first run a job can carry a first_seen from days or weeks ago. The first_seen_at/last_seen_at fields stay as the raw timestamps of your own runs.

Why did my run stop before delivering all results?

Apify caps every run at the remaining credit of the account running it. A full ai-mention run (~10,000 rows) costs about $25 at $2.50/1,000 — on a Free plan ($10/month) the run stops when your credit runs out and you receive a partial dataset. Top up credit or use a paid plan for large runs. This is platform behavior, not an actor bug.

Support

Questions, suggestions, or a source you'd like added? Open an issue on this Actor's page in Apify Console — the Actor is monitored and maintained continuously.

For developers

The pipeline is deterministic by design: fetch → parse → normalize → classify → validate → dedupe → output. Sources are plug-in adapters (one file per ATS), classification and validation are pure functions covered by unit tests, and the self-healing path only ever proposes fixes — it never edits running code. Built in Python on the Apify SDK.