# ATS Jobs Scraper: Greenhouse, Lever, Workday +15 (`panix/ats-jobs-scraper`) Actor

Scrape every open job from company career sites on Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable and 12 more ATS. Parsed salary, location, remote type and seniority in one schema. For job boards, recruiting, sales leads, hiring-trend research and new-job alerts.

- **URL**: https://apify.com/panix/ats-jobs-scraper.md
- **Developed by:** [PANIX AI LAB](https://apify.com/panix) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ATS Jobs Scraper: every job from Greenhouse, Lever, Workday and 15 more career sites

Get every open job from company career sites in one clean format. Paste a job board link, a job link, a company website or just a company name: the Actor finds the company's applicant tracking system (ATS), reads its public job feed and returns one row per job with title, location, remote type, salary, seniority, job function, skills and the full description.

It reads **18 job boards**: Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Personio, Teamtailor, BambooHR, Breezy HR, Rippling, Gem, Pinpoint, HireHive, Polymer, Manatal and Oracle Cloud HCM. No login, no API key, no browser.

**Price: $1.20 per 1,000 jobs** on paid plans (from $0.80 on higher plans), plus $0.001 per run. Filtered, duplicate and unchanged jobs, closed-job rows and companies that fail are free.

### What it does

- **Any input**: board links (`boards.greenhouse.io/stripe`), single job links, company websites (`stripe.com`) and company names (`Notion`). Mix them freely, up to 2,000 per run.
- **Finds the board for you**: a built-in directory of 244 checked companies, then the links on the company's own careers page, then board names checked against each job board's API.
- **Reads big boards completely**: Workday shows at most 2,000 jobs per search, so large Workday boards are split with the site's own filters and merged without duplicates (tested on Apify: Target's 14,000+ jobs and Capital One's 2,040 came back whole).
- **One schema for every job board**: the same fields and values whichever ATS a company uses.
- **Parsed and enriched**: city, region, country code, coordinates and time zone; remote, hybrid or on-site; employment type; seniority; job function; salary with currency, period and a yearly figure; posting date; skills; years of experience; education; visa sponsorship; description language.
- **Filters before any charge**: title words, keywords in the description, countries, states, cities, regions such as EMEA, distance from a city, workplace type, employment type, seniority, job function, department, posting date, minimum salary, visa sponsorship and language.
- **Monitoring**: on a schedule, return only jobs that are new since the last run, plus free rows for jobs that closed (with days open) and reposted jobs flagged.
- **Hiring summaries**: one row per company with open jobs, jobs posted in the last 7 and 30 days, jobs open over 90 days, remote share, jobs by function and seniority, top locations and pay ranges.
- **Ready-made company lists**: AI labs, tech, startups, fintech, remote-first, Europe, enterprise, gaming, health, climate, security and developer tools.

### Who uses it

- **Job boards and newsletters** fill niche boards with fresh jobs straight from employers and expire closed ones.
- **Recruiters and sourcers** watch target companies and get new roles the day they open.
- **Sales and RevOps teams** use hiring as a buying signal: new teams, new countries, leadership hires.
- **Job seekers** follow the companies they want to work for, filtered by role, place and pay.
- **Analysts and investors** track hiring velocity, remote mix and pay bands across a portfolio.
- **AI and RAG pipelines** get Markdown descriptions and stable IDs, through the API or Apify's MCP server.

### Why this ATS jobs scraper

- **18 job boards in one Actor**, including the enterprise systems (Workday, Oracle Cloud HCM, SmartRecruiters) that many company-name lookups miss.
- **Complete large boards**: Workday boards above the 2,000-job search cap are split and merged, so every open job is returned, not only the newest 2,000.
- **Accurate salaries**: structured pay from the job board where it exists, otherwise pay ranges read from pay-transparency sections ("$120,000 - $150,000 USD", "€60.000 - €75.000 brutto/Jahr", "₹12,00,000 per annum"), with currency, period and a yearly figure. Funding amounts, budgets and perks are not mistaken for pay.
- **Accurate locations**: "US, CA, Santa Clara", "Toronto, ON", "Remote - EMEA" and "China, Shenzhen" are all parsed into city, region and country code with a gazetteer of 31,000 cities, so country, state and distance filters work.
- **You only pay for what you keep**: filtered, duplicate, unchanged and failed jobs cost nothing, and a job whose page cannot be read is delivered free without its description.
- **Safe by default**: personal email addresses and phone numbers are removed from descriptions; role mailboxes such as careers@ stay.
- **Status for every company**: the `COMPANIES` table (JSON and CSV) says which board each input matched, how many jobs it has, how many matched your filters and why any company failed.
- **Robust**: polite per-host request limits, retries on a new IP address, resume after a platform restart, and a clean stop at your spending limit or the run timeout.

### Coming from another ATS jobs scraper?

| Common problem | How this Actor handles it |
|---|---|
| Large Workday boards stop at 2,000 jobs | Boards are split with Workday's own filters and merged, so every job comes back |
| A company name finds the wrong company | Checked directory first, then the company's own careers links; name guesses must match the board's own company name |
| Charged for empty boards, failed companies or filtered jobs | Only delivered jobs are charged |
| Salary is a raw string or missing | Min, max, currency, period and a yearly value, from the board or the description |
| "Remote" and locations are free text | City, region, country code, coordinates, remote regions such as EMEA |
| Every daily run returns the whole board again | Only new jobs, closed jobs as free rows, reposts flagged |
| No way to see which inputs worked | `COMPANIES` table with status, counts and errors per input |
| One Actor per job board | 18 job boards, one schema |

### Supported job boards

| Job board | Paste a link like | Found by company name |
|---|---|---|
| Greenhouse (also EU boards) | `boards.greenhouse.io/stripe`, `job-boards.greenhouse.io/anthropic` | Yes |
| Lever (also EU boards) | `jobs.lever.co/spotify`, `jobs.eu.lever.co/innogames` | Yes |
| Ashby | `jobs.ashbyhq.com/openai` | Yes |
| Workday | `nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`, `wd1.myworkdaysite.com/recruiting/wf/WellsFargoJobs` | Directory and website |
| SmartRecruiters | `jobs.smartrecruiters.com/BoschGroup` | Yes |
| Workable | `apply.workable.com/huggingface` | Yes |
| Recruitee | `fastned.recruitee.com` (and custom career domains) | Yes |
| Personio | `ottonova.jobs.personio.de` | Yes |
| Teamtailor | `polestar.teamtailor.com` (and custom career domains) | Yes |
| BambooHR | `401auto.bamboohr.com/careers` | Yes |
| Breezy HR | `nexo.breezy.hr` | Yes |
| Rippling | `ats.rippling.com/rippling/jobs` | Yes |
| Gem | `jobs.gem.com/retool` | Yes |
| Pinpoint | `uktv.pinpointhq.com` | Yes |
| HireHive | `focus-ireland.hirehive.com` | Yes |
| Polymer | `jobs.polymer.co/magnendo` | Yes |
| Manatal | `careers-page.com/hr-ways-3` | Yes |
| Oracle Cloud HCM | `jpmc.fa.oraclecloud.com/hcmUI/CandidateExperience/en/sites/CX_1001` | Directory and website |

Workday and Oracle sites carry tenant IDs that a name cannot be turned into: paste the career site link or the company's website, or use a name from the directory (NVIDIA, Salesforce, Visa, Target, JPMorgan Chase, Marriott, Hilton, Kroger, Uber and more).

### How to use it

1. Click **Try for free** and sign in to Apify.
2. Paste companies into **Companies**, one per line: links, websites or names. Or pick a **Ready-made company list**.
3. Optional: set filters, for example **Title includes** `data engineer` and **Locations** `Germany`.
4. Click **Start**. Open the **Jobs** view and export to JSON, CSV, Excel or HTML.

### Input examples

Every open engineering job at three companies, remote or in Germany:

```json
{
  "companies": ["https://boards.greenhouse.io/stripe", "https://jobs.ashbyhq.com/openai", "Datadog"],
  "jobFunctions": ["engineering", "data"],
  "locations": ["Germany", "Remote"]
}
```

Remote jobs with published pay at remote-first companies, newest 5 per company:

```json
{
  "companyLists": ["remote-first"],
  "workplaceTypes": ["remote"],
  "salaryOnly": true,
  "maxJobsPerCompany": 5
}
```

Senior data roles paying at least $150,000 a year in California:

```json
{
  "companyLists": ["ai", "tech"],
  "titleIncludes": ["data", "machine learning"],
  "seniorities": ["senior", "lead"],
  "locations": ["California"],
  "minSalary": 150000,
  "salaryCurrency": "USD"
}
```

A daily monitor: new jobs and closed jobs at your watchlist (schedule it, see below):

```json
{
  "companies": ["stripe.com", "linear.app", "https://jobs.lever.co/spotify"],
  "onlyNewJobs": true,
  "monitorName": "watchlist-daily"
}
```

One hiring summary per company for an account list:

```json
{
  "companies": ["stripe.com", "notion.so", "figma.com", "datadoghq.com"],
  "outputMode": "companies"
}
```

### Output

One row per job. The **Jobs**, **Salaries**, **Descriptions and skills**, **Monitoring changes** and **Company summaries** views in the dataset show the main fields; every row has the full set.

A real row from a run of the example input on Apify (November 2026), with the description shortened:

```json
{
  "rowType": "job",
  "id": "greenhouse:anthropic:5464234008",
  "title": "Data Engineer",
  "companyName": "Anthropic",
  "ats": "greenhouse",
  "url": "https://job-boards.greenhouse.io/anthropic/jobs/5464234008",
  "applyUrl": "https://job-boards.greenhouse.io/anthropic/jobs/5464234008",
  "location": "San Francisco, CA | New York City, NY; Seattle, WA",
  "city": "San Francisco",
  "region": "California",
  "regionCode": "CA",
  "country": "United States",
  "countryCode": "US",
  "workplaceType": "onsite",
  "isRemote": false,
  "employmentType": null,
  "seniority": "mid",
  "jobFunction": "data",
  "department": "Engineering & Design - Product",
  "team": null,
  "salaryMin": 320000,
  "salaryMax": 405000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "salaryAnnualMin": 320000,
  "salaryAnnualMax": 405000,
  "salaryText": "$320,000—$405,000 USD",
  "salarySource": "description",
  "postedAt": "2026-10-30T23:34:18Z",
  "postedDateApproximate": null,
  "daysSincePosted": 1,
  "postedMoreThan30DaysAgo": null,
  "updatedAt": "2026-10-30T23:37:41Z",
  "closesAt": null,
  "description": "About Anthropic\n\nAnthropic’s mission is to create reliable, interpretable, and steerable AI systems. We want AI to be safe and beneficial for our users and for society as a whole. Our team is a quickly growing group of committed researchers, engineers, policy experts, and business leaders working together to build beneficial AI systems.\n\nAbout the role ...",
  "descriptionMarkdown": null,
  "descriptionHtml": null,
  "descriptionLanguage": "en",
  "skills": ["SQL", "Python", "LLMs", "Salesforce"],
  "experienceYears": 5,
  "educationLevel": "bachelor",
  "visaSponsorship": true,
  "locations": [
    {"city": "San Francisco", "region": "California", "regionCode": "CA", "country": "United States", "countryCode": "US", "latitude": 37.775, "longitude": -122.419, "timezone": "America/Los_Angeles", "text": "San Francisco, CA"},
    {"city": "New York City", "region": "New York", "regionCode": "NY", "country": "United States", "countryCode": "US", "latitude": 40.714, "longitude": -74.006, "timezone": "America/New_York", "text": "New York City, NY"},
    {"city": "Seattle", "region": "Washington", "regionCode": "WA", "country": "United States", "countryCode": "US", "latitude": 47.606, "longitude": -122.332, "timezone": "America/Los_Angeles", "text": "Seattle, WA"}
  ],
  "countryCodes": ["US"],
  "remoteRegions": [],
  "requisitionId": "PIP-267933",
  "jobId": "5464234008",
  "boardId": "anthropic",
  "boardUrl": "https://job-boards.greenhouse.io/anthropic",
  "employmentTypeText": null,
  "extra": {"internalJobId": 4567883008},
  "input": "https://job-boards.greenhouse.io/anthropic",
  "matchedBy": "url",
  "scrapedAt": "2026-11-01T21:14:58Z",
  "schemaVersion": 1
}
```

#### Main fields

| Field | What it holds |
|---|---|
| `id` | Stable ID `ats:board:job`, the same in every run: use it to join or deduplicate |
| `title`, `companyName`, `department`, `team` | As the job board shows them |
| `url`, `applyUrl` | The job page and the application link |
| `location`, `city`, `region`, `regionCode`, `country`, `countryCode` | The main location, parsed; `locations` lists every location with coordinates and time zone |
| `workplaceType`, `isRemote`, `remoteRegions` | `remote`, `hybrid` or `onsite`; for remote jobs the regions they are open to, such as `emea` |
| `employmentType` | `full_time`, `part_time`, `contract`, `temporary`, `internship`, `apprenticeship`, `volunteer` or `other`; the board's own value is in `employmentTypeText` |
| `seniority` | `intern`, `entry`, `mid`, `senior`, `lead`, `manager`, `director`, `vp` or `executive` |
| `jobFunction` | `engineering`, `data`, `product`, `design`, `sales`, `marketing`, `customer_success`, `operations`, `finance`, `hr`, `legal`, `it`, `security`, `research` and more |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Pay as published; `salaryAnnualMin`/`salaryAnnualMax` convert hourly, daily, weekly and monthly pay to a year; `salarySource` is `ats` or `description` |
| `postedAt`, `updatedAt`, `closesAt`, `daysSincePosted` | Dates in UTC. Workday lists without a page show 'Posted 3 Days Ago', so the date is computed and `postedDateApproximate` is true |
| `description`, `descriptionMarkdown`, `descriptionHtml` | The text in the format you chose, personal emails and phone numbers removed |
| `skills`, `experienceYears`, `educationLevel`, `visaSponsorship`, `descriptionLanguage` | Read from the description |
| `changeType`, `firstSeenAt`, `closedAt`, `daysOpen`, `reposted` | With a monitor |
| `extra` | Board-specific fields such as the hiring legal entity, job family or category |

### Monitoring new jobs on a schedule

1. Set **Only new jobs since the last run** and a **Monitor name**, such as `watchlist-daily`.
2. Click **Start** once. The first run returns every open job (and is charged for them).
3. Click **Save as a new task**, then in **Schedules** create a schedule for the task, for example every morning.

Each later run returns only jobs that are new (`changeType: new`), and one free row per job that closed (`changeType: closed`, with `daysOpen`). A new job with the same title and location as a job closed in the last 30 days has `reposted: true`. Turn on **Also return updated jobs** to get jobs whose title, location, department, workplace, employment type or pay changed. To send new jobs to Slack, email or Google Sheets, add an integration to the task (Apify's Slack and Gmail integrations, or a Make, Zapier or n8n webhook).

### Pricing

You pay per delivered job, and less on higher Apify plans.

| Event | Free plan | Starter (Bronze) | Scale (Silver) | Business (Gold) and above |
|---|---|---|---|---|
| Job | $1.50 per 1,000 | $1.20 per 1,000 | $1.00 per 1,000 | $0.80 per 1,000 |
| Company summary (only when you ask for summaries) | $0.004 | $0.003 | $0.0025 | $0.002 |
| Run start | $0.001 | $0.001 | $0.001 | $0.001 |

- Free: jobs left out by filters, duplicates, jobs unchanged since the last monitoring run, closed-job rows, companies with no board or a failed board, and jobs whose page could not be read (those are delivered without a description).
- Set a spending limit on the run and the Actor stops cleanly when it is reached.
- Example: 50 companies with 40 matching jobs each are 2,000 jobs, $2.40 on the Starter plan.

### Use it from code, n8n, Make, Zapier and AI agents

Python (apify-client 3.x):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("panix/ats-jobs-scraper").call(run_input={
    "companies": ["https://boards.greenhouse.io/stripe", "Notion"],
    "titleIncludes": ["engineer"],
    "maxJobsPerCompany": 50,
})
for job in client.dataset(run.default_dataset_id).iterate_items():
    print(job["companyName"], job["title"], job["location"], job["url"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('panix/ats-jobs-scraper').call({ companies: ['stripe.com'], locations: ['Remote'] });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);
```

One HTTP request that waits for the run and returns the jobs:

```bash
curl -X POST "https://api.apify.com/v2/acts/panix~ats-jobs-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["https://jobs.ashbyhq.com/openai"], "maxJobsPerCompany": 20}'
```

- **n8n**: use the Apify node (Run an Actor and get dataset items) with `panix/ats-jobs-scraper` and the input JSON above.
- **Make** and **Zapier**: use the Apify app's "Run an Actor" action, then "Get dataset items". For a daily feed, schedule a task with a monitor and trigger on "Actor run finished".
- **AI agents (MCP)**: add `https://mcp.apify.com/?tools=panix/ats-jobs-scraper` to Claude, ChatGPT, Cursor or VS Code. Ask, for example: "List the open data engineering jobs at Stripe, Notion and Datadog posted in the last 14 days, with salary."

### FAQ

**Does it work with a company name only?**
Yes for the 244 companies in the directory and for most companies on Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee, Personio, Teamtailor, BambooHR, Breezy, Rippling, Gem, Pinpoint, HireHive, Polymer and Manatal. A guessed board must answer with the same company name, otherwise the company is reported as not found instead of returning another company's jobs. For Workday and Oracle sites, paste the career site link or the company's website. `matchedBy` says how each board was found.

**How fresh are the jobs?**
Each run reads the job boards live, so new jobs appear as soon as the company publishes them and closed jobs drop out.

**Can it search all companies by keyword?**
It reads the companies you give it or a ready-made list, then filters. Combine a list with **Title includes** and **Locations** to search across many companies.

**Why is the salary empty?**
The company publishes no pay on its board or in the description. Pay transparency laws mean most US postings in California, Colorado, New York and Washington include a range.

**Does it read LinkedIn, Indeed or Glassdoor?**
No. It reads the companies' own job boards, which is where those sites get many of their listings. Aggregator links are reported as invalid input, free.

**What happens when a board fails?**
The run goes on with the other companies. The failed company is listed in `COMPANIES` with an error code and is not charged.

**Are job descriptions complete?**
Yes, the full text the job board publishes, up to 60,000 characters. Workday, SmartRecruiters, Oracle, BambooHR, Breezy, Rippling and Polymer need one request per job for it, which is included in the price.

**How long does a run take?**
Measured on Apify with the default 512 MB: the example input (4 companies, 10 jobs each, with descriptions) takes about 15-30 seconds; 20 companies on 18 different job boards, 25 jobs each, under 2 minutes; summaries for the 50 companies of the AI list under 4 minutes; all 16,192 jobs of Target and Capital One (without descriptions) about 8 minutes. Runs with tens of thousands of jobs finish sooner with more memory (Run options → Memory, for example 2 GB), because the Actor then gets more CPU. The price per job stays the same.

### Limits

- 2,000 companies per run. Very large boards (Accenture has over 40,000 jobs on Workday) take longer with descriptions on: add filters, set **Max jobs per company**, or turn descriptions off.
- Company names cannot find Workday or Oracle sites outside the directory; paste the link or the website.
- Companies that host jobs only on their own career site software (not one of the 18 job boards) are reported as not found.
- Seniority, job function, skills and visa sponsorship are read from the text with fixed rules, so unusual titles can be classified as `mid` or `other`.

### Data and legal

The Actor reads only job postings that companies publish on public job boards for applicants, with no login. It is built for job data, not personal data: personal email addresses, phone numbers and recruiter names are not included. You are responsible for using the data in line with the laws and terms that apply to you. Not affiliated with any of the job boards named here; their names are trademarks of their owners.

Countries, regions and cities come from [GeoNames](https://www.geonames.org/), licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).

### Support

Found a problem or need another job board? Open an issue on the **Issues** tab with an example link. Output fields are only added, never renamed or removed without a note in the changelog.

# Actor input Schema

## `companies` (type: `array`):

Any mix of: a job board link (<code>https://boards.greenhouse.io/stripe</code>, <code>https://jobs.lever.co/palantir</code>, <code>https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite</code>), a single job link, a company website (<code>stripe.com</code>) or a company name (<code>Notion</code>). Supported: Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Personio, Teamtailor, BambooHR, Breezy HR, Rippling, Gem, Pinpoint, HireHive, Polymer, Manatal and Oracle Cloud HCM.

## `companyLists` (type: `array`):

No list of your own? Add every company of a ready-made list (checked monthly). Combine with filters, for example remote data jobs at AI companies.

## `excludeCompanies` (type: `array`):

Names, websites or board names to leave out, for example your own employer when you use a ready-made list.

## `titleIncludes` (type: `array`):

Keep jobs whose title contains at least one of these words or phrases, for example <code>data engineer</code>, <code>product manager</code>, <code>C++</code>.

## `titleExcludes` (type: `array`):

Leave out jobs whose title contains any of these, for example <code>intern</code>, <code>senior</code>, <code>contract</code>.

## `keywords` (type: `array`):

Keep jobs that mention at least one of these in the title or the job description, such as <code>Snowflake</code>, <code>Kubernetes</code> or <code>visa</code>.

## `excludeKeywords` (type: `array`):

Leave out jobs whose title or description mentions any of these, for example <code>security clearance</code>.

## `locations` (type: `array`):

Countries (<code>Germany</code>, <code>DE</code>), US states or provinces (<code>California</code>, <code>Ontario</code>), cities (<code>London</code>, <code>Austin, TX</code>), regions (<code>EMEA</code>, <code>Europe</code>, <code>APAC</code>, <code>LATAM</code>, <code>DACH</code>, <code>Nordics</code>) or <code>Remote</code>. A remote job open to EMEA matches Germany.

## `excludeLocations` (type: `array`):

Leave out jobs located in any of these countries, states, cities or regions.

## `workplaceTypes` (type: `array`):

Remote, hybrid or on-site. A job with no workplace information counts as on-site.

## `employmentTypes` (type: `array`):

From the job board's own field, or the title ('Intern', 'Part-time'). A job with no employment information counts as full-time.

## `seniorities` (type: `array`):

Read from the job title (Senior, Staff, Director, Intern...) and the board's experience level. Titles without a level count as mid level.

## `jobFunctions` (type: `array`):

Read from the job title, team and department.

## `departments` (type: `array`):

Keep jobs whose department or team contains one of these, for example <code>Engineering</code> or <code>Sales</code>.

## `postedWithinDays` (type: `integer`):

Only jobs posted in the last N days. Jobs whose board shows no date are left out.

## `postedAfter` (type: `string`):

A date such as 2026-10-01, or a relative value such as '2 weeks'.

## `salaryOnly` (type: `boolean`):

Keep jobs whose board publishes pay, or whose description states a pay range.

## `minSalary` (type: `integer`):

Keep jobs whose yearly pay (hourly and monthly pay converted) reaches this amount. Jobs without pay information are left out.

## `salaryCurrency` (type: `string`):

Three-letter code for the minimum salary, for example <code>USD</code>, <code>EUR</code> or <code>GBP</code>. Jobs paid in other currencies are left out.

## `visaSponsorshipOnly` (type: `boolean`):

Keep jobs whose description says sponsorship is available. Jobs that say it is not, or say nothing, are left out.

## `languages` (type: `array`):

Keep jobs written in these languages (from the board, or detected from the text).

## `nearLocation` (type: `string`):

Keep jobs within the distance below of this city, for example <code>Berlin</code> or <code>Austin, TX</code>, measured between city centers.

## `radiusKm` (type: `integer`):

Used with 'Near a city'.

## `maxJobsPerCompany` (type: `integer`):

Newest jobs first. Empty = every matching job (boards with 10,000+ jobs are read completely).

## `maxItems` (type: `integer`):

Stop the run after this many jobs. Empty = no limit (your spending limit still applies).

## `includeDescription` (type: `boolean`):

The full job text, plus skills, years of experience, education, visa sponsorship and pay found in it. Some boards need one extra request per job for it, included in the price.

## `descriptionFormat` (type: `string`):

Plain text for spreadsheets, Markdown for AI and RAG pipelines, HTML (cleaned) for job boards, or all three. Personal emails and phone numbers are removed.

## `outputMode` (type: `string`):

Job rows, one hiring summary row per company (open jobs, recent postings, functions, locations, pay ranges), or both.

## `jobUrlMode` (type: `string`):

What a pasted link to a single job returns.

## `includeRawData` (type: `boolean`):

The unmodified job record from the job board in a <code>raw</code> field, for fields this Actor does not normalize.

## `onlyNewJobs` (type: `boolean`):

Returns jobs not seen in earlier runs (<code>changeType: new</code>), and closed jobs as free rows. Unchanged jobs are skipped and free. The first run returns every job.

## `monitorName` (type: `string`):

Any name, such as <code>ai-companies-daily</code>. Each name keeps its own memory in your account (key-value store <code>ats-jobs-scraper-monitors</code>). Without 'Only new jobs', every job is returned with <code>changeType</code> new, updated or unchanged.

## `includeUpdatedJobs` (type: `boolean`):

With 'Only new jobs': also return jobs whose title, location, department, workplace, employment type or pay changed (<code>changeType: updated</code>, charged as a job).

## `includeClosedJobs` (type: `boolean`):

With a monitor: one free row per job that disappeared from its board since the last run (<code>changeType: closed</code>, with days open).

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy by default: every retry comes from a new IP address.

## `maxConcurrency` (type: `integer`):

How many job boards are read at the same time. Each job board also has its own polite request limit.

## Actor input object example

```json
{
  "companies": [
    "https://job-boards.greenhouse.io/anthropic",
    "https://jobs.ashbyhq.com/ramp",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "Notion"
  ],
  "salaryOnly": false,
  "visaSponsorshipOnly": false,
  "radiusKm": 50,
  "maxJobsPerCompany": 10,
  "includeDescription": true,
  "descriptionFormat": "text",
  "outputMode": "jobs",
  "jobUrlMode": "job",
  "includeRawData": false,
  "onlyNewJobs": false,
  "includeUpdatedJobs": false,
  "includeClosedJobs": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 6
}
```

# Actor output Schema

## `jobs` (type: `string`):

Delivered jobs. Filtered, duplicate and failed jobs are not in the dataset and are not charged.

## `companies` (type: `string`):

Which job board each company was matched to, how many jobs it has, how many matched and why any company failed.

## `companiesCsv` (type: `string`):

The same table as COMPANIES, ready for Excel or Google Sheets.

## `summary` (type: `string`):

Totals, jobs left out by each filter, jobs per job board, request statistics and warnings.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companies": [
        "https://job-boards.greenhouse.io/anthropic",
        "https://jobs.ashbyhq.com/ramp",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "Notion"
    ],
    "maxJobsPerCompany": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("panix/ats-jobs-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "companies": [
        "https://job-boards.greenhouse.io/anthropic",
        "https://jobs.ashbyhq.com/ramp",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "Notion",
    ],
    "maxJobsPerCompany": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("panix/ats-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    "https://job-boards.greenhouse.io/anthropic",
    "https://jobs.ashbyhq.com/ramp",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "Notion"
  ],
  "maxJobsPerCompany": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call panix/ats-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,panix/ats-jobs-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Mpc1jzWwx0dyN4hf2/builds/KldSnKXiB8ebiSVbJ/openapi.json
