Ashby Jobs Scraper - Fast ATS API avatar

Ashby Jobs Scraper - Fast ATS API

Pricing

Pay per event

Go to Apify Store
Ashby Jobs Scraper - Fast ATS API

Ashby Jobs Scraper - Fast ATS API

Jobs from Ashby boards (OpenAI, Notion, Linear, Ramp, Perplexity, hundreds more). Structured salary + equity + bonus, filters + diff mode. New `report` mode: 1 row/company with hiringScore, velocity, priorityRoles, remoteShare. $0.50/1k jobs or $0.025/report.

Pricing

Pay per event

Rating

0.0

(0)

Developer

An Tan Huynh

An Tan Huynh

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

2 days ago

Last modified

Share

Ashby Jobs Scraper – Fast ATS API

Scrape Ashby-hosted career pages via the public JSON API. One row per job with structured compensation (salary min/max, equity, bonus), workplaceType, department, team and descriptionPlain – no proxy required.

$0.50 per 1,000 jobs ($0.0005 / job, pay-per-event).

Who is this for?

Ashby is the ATS of choice for AI-first and modern SaaS startups. Boards you can scrape today include OpenAI, Notion, Linear, Ramp, Perplexity, Vercel, Supabase, Clay, Modal, Hex, Rippling, Mercury, Loom and hundreds more. If a job board URL looks like https://jobs.ashbyhq.com/<company>, this actor can scrape it.

Input

FieldTypeDefaultNotes
boardSlugsstring[]requiredCompany slugs or full board URLs. The actor extracts the slug automatically. Pass as many companies as you want in a single run.
includeCompensationbooltrueAppend ?includeCompensation=true to pull structured salary + equity + bonus for boards that opt in.
maxJobsPerBoardint5000Safety cap per board (OpenAI has ~800).
titleKeywordsstring[](empty)Keep only jobs whose title contains any of these (case-insensitive). Example: ["engineer","research scientist","ml"].
titleExclusionsstring[](empty)Drop jobs whose title contains any of these. Example: ["senior","manager","staff"].
departmentsstring[](empty)Case-insensitive substring match on job department.
locationsstring[](empty)Case-insensitive substring match on location / country / region / locality / secondary locations.
workplaceTypesstring[](empty)Match normalised workplaceType: remote, hybrid, onsite.
employmentTypesstring[](empty)Match employmentType: fulltime, parttime, contract, temporary, intern.
onlyWithSalaryboolfalseKeep only jobs where the compensation has a numeric Salary component.
onlyRemoteboolfalseShortcut – keep only jobs with workplaceType=Remote or isRemote=true.
publishedAfterstring(empty)ISO date / datetime cut-off on publishedAt.
minSalaryint(empty)Keep only jobs whose compensation annualises to at least this amount. Hourly rates are multiplied by 2080, monthly by 12. Jobs without a numeric salary are dropped.
salaryCurrencystring(empty)ISO 4217 currency filter (USD, EUR, GBP...). When set, jobs in other currencies are dropped.
onlyNewSinceLastRunboolfalseDiff mode. The actor remembers (per stateKey + board) the set of jobIds seen on previous runs in a named key-value store, and on each subsequent run only pushes jobs that are new. Every pushed row carries isNew: true. Pair with Apify Scheduler for daily deltas.
stateKeystringdefaultOptional label for the diff state bucket. Different stateKey values keep independent "seen" memories; shared values share memory.
proxyConfigurationobject(none)Optional. API is open; use proxy only if you hit rate limits.

Example input:

{
"boardSlugs": ["openai", "notion", "linear"],
"includeCompensation": true,
"maxJobsPerBoard": 5000
}

Output (one row per job)

{
"boardSlug": "openai",
"jobId": "8fb1615c-34bf-47c4-a1d1-b7b2f836bbd3",
"title": "Technical Program Manager, Compute Infrastructure",
"jobUrl": "https://jobs.ashbyhq.com/openai/8fb1615c-34bf-47c4-a1d1-b7b2f836bbd3",
"applyUrl": "https://jobs.ashbyhq.com/openai/8fb1615c-34bf-47c4-a1d1-b7b2f836bbd3/application",
"location": "San Francisco",
"secondaryLocations": [],
"country": "United States",
"region": "California",
"locality": "San Francisco",
"workplaceType": "Hybrid",
"workplaceTypeRaw": null,
"isRemote": false,
"employmentType": "FullTime",
"department": "Technical Program Management",
"team": "Technical Program Management",
"isListed": true,
"publishedAt": "2026-03-12T16:38:15.322+00:00",
"salaryMin": 257000,
"salaryMax": 335000,
"salaryCurrency": "USD",
"salaryInterval": "1 YEAR",
"equitySummary": "Offers Equity",
"bonusSummary": null,
"commissionSummary": null,
"compensationSummary": "$257K – $335K • Offers Equity",
"shouldDisplayCompensation": true,
"compensation": {"...": "...raw compensation object..."},
"descriptionPlain": "ABOUT THE TEAM\n\nThe compute infrastructure team...",
"descriptionHtml": "<h3><strong>About the Team</strong></h3>...",
"scrapedAt": "2026-10-15T21:04:00+00:00"
}

Workplace type normalisation

The actor maps workplaceType (and isRemote as fallback) to one of Remote, Hybrid, Onsite, or leaves it null when the board doesn't publish the attribute.

Compensation

Ashby stores compensation as a tiered object. The actor flattens the primary Salary component into salaryMin / salaryMax / salaryCurrency / salaryInterval, and surfaces human text for equitySummary, bonusSummary, commissionSummary and the overall compensationSummary. The full raw compensation object is kept too for advanced consumers (multi-tier roles, geographic salary bands).

Boards that do publish pay (OpenAI, Ramp, Ashby itself) populate salary fields on ~80–96 % of listings; boards that don't (Notion, Linear) leave the compensation object empty.

Smoke run numbers (2026-10-16)

InputBoardsRowsField coverage
Default smoke (3 boards, with compensation)openai + notion + linear965100 % jobId/title/jobUrl/location/employmentType/department/publishedAt/descriptionPlain/descriptionHtml; 69 % workplaceType; 67 % salaryMin
Filtered (engineering + remote/hybrid + onlyWithSalary)openai + ramp48100 % salary present, 34 Engineering + 14 Forward Deployed Engineering, 47 Hybrid + 1 Remote
publishedAfter 2026-09-01, employmentTypes=[fulltime]ramp690 violations, 100 % FullTime

Per-board workplace coverage: OpenAI 68 %, Notion 64 %, Linear 100 %, Ramp 100 %. Boards that don't tag workplace leave it null – no guess is made.

Pricing

Pay-per-event. Two charge types:

  • $0.0005 per job row pushed (default mode: "jobs").
  • $0.025 per report row pushed (mode: "report", one row per company).

Example runs:

  • OpenAI + Notion + Linear (965 jobs, jobs mode) → $0.48.
  • Ramp only, published after 2026-09-01, full-time (69 jobs) → $0.03.
  • Filtered OpenAI + Ramp engineering roles with pay (48 jobs) → $0.02.
  • OpenAI + Notion + Linear in report mode → $0.075 (3 reports; OpenAI score 90 / 808 open roles, Notion 90 / 135, Linear 55 / 29).

Compute cost is almost zero (direct API, no proxy, ~1 request/board).

Report mode (mode: "report")

Instead of one row per job, emit one hiring-signal report per company. Each report row carries:

  • totalOpenRoles + hiringScore 0-100 + hiringLabel (aggressive_hiring / active_hiring / steady_hiring / low_hiring / no_signal).
  • hiringVelocity: { recentWindowDays, netOpenRolesChange, hadPreviousRun, previousTotal } — the delta vs the previous run of the same stateKey.
  • priorityRoles[]: top 5 role families (engineering, data, research, product, design, sales, customer_success, support, marketing, operations, finance, legal, people_hr, security, other) with example titles.
  • departmentSignals[], regionSignals[] (us / canada / europe_uk / europe_eu / latam / mena / apac / africa / remote_global / remote_other / other / unknown), remoteShare 0.0-1.0, seniorityMix (junior / mid / senior / leadership).
  • keywordHits: user-supplied strings mapped to how many open titles contain each (case-insensitive substring).
  • expansionSignals: newDepartments[], newRegions[], newRoleFamilies[] compared to the previous run.
  • recommendedOutreach[]: short English suggestions for BD / sales / talent outreach based on the above signals.
  • reportConfidence 0.1-1.0 plus warnings[].

Example input:

{
"boardSlugs": ["openai", "notion", "linear"],
"mode": "report",
"keywordHits": ["AI", "ML", "LLM"],
"stateKey": "weekly-pipeline"
}

Previous-run deltas live in the named key-value store ashby-report-<stateKey> on your account.

Daily deltas (onlyNewSinceLastRun)

Pair with Apify Scheduler to get only newly-posted jobs each run. The first run of a given (stateKey, boardSlug) records every open jobId and pushes the first maxJobsPerBoard rows (all tagged isNew: true). Every later run compares the current open set against the stored one and emits only rows whose jobId is new.

{
"boardSlugs": ["openai", "notion", "linear"],
"onlyNewSinceLastRun": true,
"stateKey": "daily-pipeline",
"titleKeywords": ["engineer"],
"minSalary": 250000,
"salaryCurrency": "USD"
}

The dedup state lives in a named key-value store ashby-diff-<stateKey> on your account; delete it from the Apify Console to force the next run to treat every job as new. Use different stateKey names for independent downstream pipelines.

Notes

  • Ashby returns every open job on a board in one JSON response (no pagination). maxJobsPerBoard is a safety trim for big boards.
  • publishedAt is ISO 8601 with timezone offset exactly as returned by the API.
  • Jobs where isListed: false are skipped (they are present in the API but intentionally hidden by the employer).
  • Unknown slugs return HTTP 404 – the actor logs and skips. Some companies that look Ashby-flavoured actually live on Greenhouse (eg anthropic, perplexity-ai) – see our companion Greenhouse scraper.
  • You can paste the full board URL (https://jobs.ashbyhq.com/openai) instead of just the slug – the slug is extracted automatically.