# Greenhouse Jobs Scraper: Workday, Lever + Visa Flags (`chimey_forearm/ats-jobs-scraper`) Actor

Greenhouse jobs and Workday jobs scraper, plus Lever, Ashby and 4 more ATSs in one schema. Visa sponsorship, US citizenship, ITAR and clearance flags, salary, remote, job alerts. No login. Export data, run via API, schedule and monitor runs, or integrate with other tools.

- **URL**: https://apify.com/chimey_forearm/ats-jobs-scraper.md
- **Developed by:** [Mohamed Bahaa](https://apify.com/chimey_forearm) (community)
- **Categories:** Jobs, AI, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 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.

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

### What does Greenhouse & Workday Jobs Scraper do?

> **Career site job scraper: Greenhouse jobs scraper, Workday jobs scraper and job listing API in one.** Every job is flagged for visa sponsorship, US citizenship, ITAR and security clearance, with filters that skip those jobs before you pay.

![Greenhouse Jobs Scraper output table: jobs with company, ATS, location, pay, visa sponsorship, citizenship, ITAR and clearance flags](https://api.apify.com/v2/key-value-stores/ZA74NSNlX7nM76ZW5/records/ats-output.png)

| What you can extract | Features & integrations |
|---|---|
| 💼 **Job basics**: title, company, department, team | **8 ATSs, one schema**: board URLs, careers pages or company slugs |
| 📍 **Location**: locations, remote flag, employment type | **Filters**: keywords, departments, locations, remote only |
| 💰 **Salary range**: when the board publishes one | **Skip before you pay**: drop no-sponsorship or clearance jobs |
| 📅 **Posted date & apply URL**: link straight to the application | **Only new jobs**: daily job alerts with posted-within filter |
| 📝 **Description**: plain text and Markdown | **Scheduling**: run it hourly, daily or weekly with Apify schedules |
| 🛂 **Visa sponsorship flag**: offered or not offered, with the evidence sentence | **Export anywhere**: JSON, CSV, Excel, XML or HTML from the dataset |
| 🇺🇸 **Citizenship / ITAR / clearance flags**: each with the sentence it came from | **API & SDKs**: Apify REST API plus JavaScript and Python clients |
| 🏢 **Source ATS**: Greenhouse, Lever, Ashby, Workday and 4 more | **AI agents (MCP)**: call it from Claude or other agents via Apify's MCP server |

**Try it free in 1 click:** open this [ready-made example](https://apify.com/chimey_forearm/ats-jobs-scraper/examples/find-remote-frontend-jobs-at-top-startups) and press Start. Apify's free plan includes $5 of usage every month, no credit card needed. The Input example below returned 16 records and costs about $0.02 at list price.

It is a **jobs scraper** that pulls **job postings straight from company career boards**, then flags each job for **visa sponsorship**, US citizenship, ITAR and security clearance.

- **Greenhouse jobs scraper**, **Lever jobs scraper**, **Ashby jobs scraper** and **Workday jobs scraper**, plus **Workable**, **SmartRecruiters**, **Recruitee** and **Personio**, all in **one normalized schema**
- **One job API across 8 ATSs**: instead of calling and parsing each board's own API yourself, you send board URLs, careers pages or bare company slugs (`stripe`, `ramp`, `notion`) and get one format back
- **Visa sponsorship jobs filter**: `workAuthorization` on every job (sponsorship `offered` / `not_offered`, US citizenship, US person / ITAR, export control, security clearance `required` / `preferred`) with the `evidence` sentence. `excludeNoSponsorship` and `excludeCitizenshipOrClearance` drop those jobs before they are charged. In our test on 6 boards, 19 of 72 engineering jobs were dropped by those switches
- **Workday career sites**: paste a `*.myworkdayjobs.com` URL (NVIDIA, Target, CrowdStrike, Workday…) and get the same clean schema, with full description, exact post date and every location
- **Auto-detect**: a bare company slug is matched to the ATS the company uses (Workday needs its careers-site URL). **Careers-page detection**: paste `https://ramp.com/careers` and it finds the linked or embedded board
- **Salary / compensation**: structured pay from Ashby and Lever, plus pay ranges found in the description text for Greenhouse and others (`compensation.source` tells you which)
- **Job alerts with only new jobs**: turn on `onlyNewJobs` and scheduled runs return just the openings you haven't seen yet, so you only pay for new jobs
- **Filters**: title keywords (include and exclude), location contains, remote only, department/team, posted within N days, max jobs per company
- **No duplicates**: the same job reached through two inputs (say `stripe` and `boards.greenhouse.io/stripe`) is saved once
- **No login, no browser, no proxies**: uses each ATS's public JSON job-board API and runs in 256 MB, with retries, backoff and polite per-host rate limiting
- **LLM- and AI-agent-ready**: descriptions as clean Markdown, callable through the Apify MCP server

The work-authorization flags come from plain-text rules on the job description, not AI, so check `evidence` before you rely on a flag. Jobs without a description get `workAuthorization: null`.

### What data can Greenhouse & Workday Jobs Scraper extract?

| | | |
|---|---|---|
| 🏷️ `type`: `job` or `error` | 🧩 `ats`: Which ATS the board runs on | 🏢 `company`: Company name |
| 🔤 `companySlug`: Company slug on the ATS | 🆔 `jobId`: The ATS's own job ID | 💼 `title`: Job title |
| 🗂️ `department`: Department | 👥 `team`: Team | 📍 `location`: Main location |
| 🗺️ `locations`: Every listed location | 🌍 `country`: Country when the ATS gives one | 🏠 `remote`: Remote flag (true/false) |
| 🏢 `workplaceType`: On-site, hybrid or remote, as the ATS says | ⏱️ `employmentType`: Full-time, contract and so on | 💰 `compensation`: Salary range: summary, min, max, currency, interval, source |
| 📅 `postedAt`: Date posted | 🔄 `updatedAt`: Last updated, when given | 🔗 `jobUrl`: Job page |
| ✅ `applyUrl`: Direct apply link | 📋 `boardUrl`: The company's job board | 📝 `descriptionText`: Description as plain text |
| 🧾 `descriptionMarkdown`: Description as Markdown | 🧱 `descriptionHtml`: Original HTML (with `includeHtml`) | 🕒 `scrapedAt`: When it was scraped |
| 🛂 `workAuthorization.sponsorship`: Visa sponsorship: `offered`, `not_offered` or null | 🇺🇸 `workAuthorization.usCitizenshipRequired`: US citizenship required | 🛡️ `workAuthorization.usPersonRequired`: US person / ITAR required |
| 📦 `workAuthorization.exportControlled`: Export-controlled role | 🔐 `workAuthorization.securityClearance`: Clearance: `required`, `preferred` or null | 🔎 `workAuthorization.evidence`: The sentences each flag came from |

### How to use Greenhouse & Workday Jobs Scraper in 5 steps

1. Create a free [Apify account](https://console.apify.com/sign-up).
2. Open [Greenhouse & Workday Jobs Scraper](https://apify.com/chimey_forearm/ats-jobs-scraper).
3. Add your input: board URLs (`https://boards.greenhouse.io/stripe`, `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`), careers pages or slugs like `notion`, plus optional filters. Need visa sponsorship, or can't hold a clearance? Switch on **Skip jobs that say no visa sponsorship** and/or **Skip jobs that need US citizenship, US-person (ITAR) status or a clearance**. For alerts, switch on **Only new jobs since last run**.
4. Click **Start**.
5. Download the results as JSON, CSV or Excel (or use the API), or schedule the run daily so each run brings only the new openings.

### Input

This exact input was run on Oct 19 2026 (256 MB): one real Greenhouse board and one board that doesn't exist, to show both a job and an error item. Paste it into the **Input** tab (JSON view) and click **Start**.

```json
{
  "companies": [
    "https://boards.greenhouse.io/affirm",
    "https://boards.greenhouse.io/zzznotreal123"
  ],
  "keywords": ["engineer"],
  "maxJobsPerCompany": 15,
  "includeDescription": true
}
```

Ready-made example Tasks (open one and click **Start**):

- [Find remote frontend jobs at top startups](https://apify.com/chimey_forearm/ats-jobs-scraper/examples/find-remote-frontend-jobs-at-top-startups)
- [Track new engineering jobs posted this week](https://apify.com/chimey_forearm/ats-jobs-scraper/examples/track-new-engineering-jobs-posted-this-week)
- [Benchmark product manager salaries from job boards](https://apify.com/chimey_forearm/ats-jobs-scraper/examples/benchmark-product-manager-salaries-from-job-boards)
- [Scrape Workday jobs from a company career site](https://apify.com/chimey_forearm/ats-jobs-scraper/examples/scrape-workday-jobs-from-a-company-career-site)
- [New job alerts from company career pages](https://apify.com/chimey_forearm/ats-jobs-scraper/examples/new-job-alerts-from-company-career-pages)

#### Supported inputs

| ATS | Accepted formats |
|---|---|
| Greenhouse | `boards.greenhouse.io/stripe`, `job-boards.greenhouse.io/airbnb`, `.../jobs/<id>`, embed `?for=<slug>`, `?gh_jid=<id>` |
| Lever | `jobs.lever.co/spotify`, `jobs.lever.co/<slug>/<postingId>`, `jobs.eu.lever.co/<slug>` |
| Ashby | `jobs.ashbyhq.com/ramp`, `jobs.ashbyhq.com/<slug>/<jobId>` |
| Workable | `apply.workable.com/<slug>`, `apply.workable.com/<slug>/j/<shortcode>`, `<slug>.workable.com` |
| SmartRecruiters | `jobs.smartrecruiters.com/<CompanyId>`, `careers.smartrecruiters.com/<CompanyId>` |
| Recruitee | `<slug>.recruitee.com`, `<slug>.recruitee.com/o/<offer>` |
| Personio | `<slug>.jobs.personio.de`, `<slug>.jobs.personio.com`, `.../job/<id>` |
| Workday | `<tenant>.wd5.myworkdayjobs.com/<Site>` (any `wdN`, with or without `/en-US/`), `.../job/<location>/<title>_<id>`, `wd1.myworkdaysite.com/recruiting/<tenant>/<Site>` |
| Any except Workday | bare slug, e.g. `stripe`, `notion`, `Ubisoft2` (tries Greenhouse → Lever → Ashby → SmartRecruiters → Workable → Recruitee → Personio) |
| Company site | a careers page URL such as `https://ramp.com/careers` (scanned for a linked or embedded board, including Workday) |

#### Input fields

| Field | Description |
|---|---|
| `companies` | Board URLs, job URLs, careers pages or bare slugs (required) |
| `keywords` / `excludeKeywords` | Title must contain any keyword / none of the excluded ones (case-insensitive) |
| `locations` | Any location of the job contains any of these strings |
| `remoteOnly` | Only jobs flagged remote |
| `departments` | Department or team contains any of these |
| `postedWithinDays` | Only jobs first published in the last N days (0 = any) |
| `maxJobsPerCompany` | Cap per company after filters (default 500, 0 = no limit) |
| `includeDescription` | Description as `descriptionText` + `descriptionMarkdown` (default on) |
| `includeHtml` | Also keep the original description HTML |
| `atsToTry` | Which ATSs to try for bare slugs, in order |
| `detectFromCareerPage` | Scan non-ATS URLs for an embedded board (default on) |
| `excludeNoSponsorship` | Skip jobs whose description says visa sponsorship is not available |
| `excludeCitizenshipOrClearance` | Skip jobs that need US citizenship, US-person (ITAR) status or a security clearance |
| `onlyNewJobs` | Output only jobs not returned by an earlier run with the same memory (default off). The first run returns everything and saves the baseline |
| `stateKey` | Optional name for that memory, e.g. `frontend-alerts`. Empty = one memory per company list |

### Output

Every record has a `type`: `job` or `error`. A real record from the run above (description shortened):

```json
{
  "type": "job",
  "ats": "greenhouse",
  "company": "Affirm",
  "companySlug": "affirm",
  "jobId": "8010489003",
  "title": "Analytics Engineer II",
  "department": "Accounting",
  "team": null,
  "location": "Remote Spain",
  "locations": [
    "Remote Spain",
    "Remote Poland"
  ],
  "country": null,
  "remote": true,
  "workplaceType": null,
  "employmentType": null,
  "compensation": {
    "summary": "€63,000 - €99,000",
    "min": 63000,
    "max": 99000,
    "currency": "EUR",
    "interval": "YEAR",
    "source": "description"
  },
  "postedAt": "2026-10-01T14:33:52.000Z",
  "updatedAt": "2026-10-16T21:13:47.000Z",
  "jobUrl": "https://job-boards.greenhouse.io/affirm/jobs/8010489003",
  "applyUrl": "https://job-boards.greenhouse.io/affirm/jobs/8010489003",
  "boardUrl": "https://job-boards.greenhouse.io/affirm",
  "scrapedAt": "2026-10-20T01:40:57.996Z",
  "workAuthorization": {
    "sponsorship": "offered",
    "usCitizenshipRequired": false,
    "usPersonRequired": false,
    "exportControlled": false,
    "securityClearance": null,
    "evidence": [
      "We are able to offer visa sponsorship for this role, but do require that someone is based in Spain for the role."
    ]
  },
  "descriptionText": "At Affirm, we exist for the moments that matter—giving people a clear, predictable way to pay over time, with no hidden  ...",
  "descriptionMarkdown": "At Affirm, we exist for the moments that matter—giving people a clear, predictable way to pay over time, with no hidden  ..."
}
```

A clearance example from an earlier test run (SpaceX board, Oct 18 2026, trimmed):

```json
{
  "company": "SpaceX",
  "ats": "greenhouse",
  "title": "AI Engineer, Special Programs",
  "location": "Washington, DC",
  "workAuthorization": {
    "sponsorship": null,
    "usCitizenshipRequired": false,
    "usPersonRequired": true,
    "exportControlled": true,
    "securityClearance": "required",
    "evidence": [
      "- To conform to US Government export regulations, applicant must be a (i) US citizen or national, (ii) US lawful, permanent resident (aka green card holder), (iii) Refugee under 8 USC.",
      "- This position requires successfully obtaining and maintaining a Top Secret Security Clearance as a condition of employment.",
      "ITAR REQUIREMENTS:"
    ]
  },
  "applyUrl": "https://boards.greenhouse.io/spacex/jobs/8557208002?gh_jid=8557208002"
}
```

You can download the dataset as JSON, CSV, Excel, XML or HTML.

### How can I use the data?

- **Job aggregation**: build a niche job board (remote, AI, climate, frontend, startups) from hundreds of company boards
- **Visa sponsorship job search**: keep only jobs that don't rule out sponsorship, or that need no clearance
- **HR tech and recruiting**: hiring signals, competitor hiring trends, headcount by department and location
- **Sales intelligence**: find companies hiring for roles that signal they need your product
- **Salary research**: collect pay ranges for a role across companies
- **AI agents and job-search copilots**: feed fresh, structured postings to an LLM to match candidates to jobs
- **Personal job search**: watch your dream companies on a schedule and get only new matching roles

### More Actors from the same developer

| Actor | What it does |
|---|---|
| [Telegram Channel Scraper](https://apify.com/chimey_forearm/telegram-channel-scraper) | Public Telegram channel posts with a keyword monitor and only-new mode |
| [Substack Scraper](https://apify.com/chimey_forearm/substack-to-markdown) | Substack newsletters to clean Markdown, plus podcast transcripts |
| [App Store & Google Play Reviews Scraper](https://apify.com/chimey_forearm/app-reviews-scraper) | Reviews from both stores in one run, only new reviews on schedules |
| [Website to Markdown Crawler](https://apify.com/chimey_forearm/sitemap-to-markdown) | Any website to Markdown for RAG, with incremental sync and llms.txt |
| [Government Bids & RFP Scraper](https://apify.com/chimey_forearm/opengov-bids-scraper) | Open bids and RFPs from 500+ US city and county portals on OpenGov |
| [State Bids Scraper](https://apify.com/chimey_forearm/state-bids-scraper) | Open bids from COMMBUYS, BidBuy, NJSTART, OregonBuys and NevadaEPro |
| [PERM Green Card Sponsors](https://apify.com/chimey_forearm/perm-green-card-sponsors) | Companies that sponsor green cards, from official DOL PERM data |

### Error items

The run never silently returns nothing for an input: every input that can't be scraped gets one record with `type: "error"`. The real error item from the run above:

```json
{
  "type": "error",
  "input": "https://boards.greenhouse.io/zzznotreal123",
  "error": "BOARD_NOT_FOUND",
  "errorMessage": "No public greenhouse job board found for \"zzznotreal123\" (or it has no open jobs).",
  "ats": "greenhouse",
  "companySlug": "zzznotreal123",
  "scrapedAt": "2026-10-20T01:40:58.261Z"
}
```

Fields: `type`, `input`, `error`, `errorMessage`, `scrapedAt`, plus `ats` and `companySlug` when known, or `tried` (the ATSs checked) for bare slugs.

| `error` | When |
|---|---|
| `BOARD_NOT_FOUND` | No public board (or job) found for that URL or slug |
| `NO_OPEN_JOBS` | The board exists but has no open jobs right now |
| `JOB_NOT_FOUND` | A job URL whose job is not open on that board |
| `UNSUPPORTED_URL` | Not a supported job board, and no board was found on the page |
| `FETCH_FAILED` | A request failed, a page couldn't be loaded, or an unexpected error |

Filter them out with `type = job`. Error items are charged as dataset items (one per failed input). A `RUN_SUMMARY` record in the key-value store gives `boards`, `jobs`, `errors`, `duplicatesSkipped`, `skippedSeenBefore` and `droppedByWorkAuthFilter`. If the run reaches your maximum cost per run, it stops cleanly and logs it (no error item).

### Tips

- Company slugs can differ from the company name (`palantir` on Lever, `Ubisoft2` on SmartRecruiters). If a bare slug isn't found, paste the board URL or the company's careers page.
- For daily monitoring, schedule the actor with `onlyNewJobs: true` and your keywords: every run returns only openings it hasn't returned before. The memory lives in your own key-value store named `ats-jobs-scraper-state`; delete a key there (or change `stateKey`) to start fresh.
- Workday's list only says "3 Locations" for multi-location jobs. Keep `includeDescription` on (the default), or use a location filter, and the actor opens each kept job to fill in every location and the exact post date. Workday's public list shows at most 2,000 jobs per site, so add a keyword for very large employers.
- With exactly one keyword, SmartRecruiters is searched server-side, so even 5,000-job boards stay fast.
- Workable rate-limits aggressive traffic; the actor backs off automatically and reports `FETCH_FAILED` only if Workable keeps refusing.

### FAQ

**How much does it cost?** Pay per event, no subscription: **$0.001 per job** saved to the dataset (error records are charged as dataset items too, one per failed input) and **$0.00005 per run start**. 1,000 jobs ≈ **$1**. Platform usage is included, so you don't pay compute on top. Set a maximum cost per run and the Actor stops cleanly when it's reached. See the [Pricing tab](https://apify.com/chimey_forearm/ats-jobs-scraper/pricing).

**Which integrations work?** Any Apify integration: Make, Zapier, n8n, Google Sheets, Slack, webhooks, or schedules that run it hourly, daily or weekly.

**Can I call it from the API?** Yes. Node.js with `apify-client`:

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('chimey_forearm/ats-jobs-scraper').call({
    companies: ['https://boards.greenhouse.io/affirm'],
    keywords: ['engineer'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

Python with `apify-client`:

```python
from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("chimey_forearm/ats-jobs-scraper").call(run_input={
    "companies": ["https://boards.greenhouse.io/affirm"],
    "keywords": ["engineer"],
})
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

**Can I use it from an AI agent (MCP)?** Yes. Add it to Claude or another MCP client through the Apify MCP server (`https://mcp.apify.com?actors=chimey_forearm/ats-jobs-scraper`). Output is flat JSON with Markdown descriptions, ideal for LLM tools.

**Does it support Workday?** Yes. Paste the company's Workday careers-site URL (for example `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`); it uses Workday's public JSON endpoint, no browser. Bare slugs can't be guessed for Workday because each company picks its own site name. iCIMS and Taleo are not supported.

**How does "only new jobs" work?** The Actor saves the IDs of jobs it returned in a key-value store in your Apify account. The next run with the same company list (or the same `stateKey`) skips those IDs, so you only get, and only pay for, new postings. Changing filters can surface jobs that were filtered out before, as "new".

**How do the visa / citizenship / clearance flags work?** The Actor reads each job description for phrases like "visa sponsorship is not available", "unable to sponsor", "must be a US citizen", ITAR "US person" rules and "active TS/SCI clearance". Clearance mentioned as "beneficial" or "preferred" is marked `preferred` and is not dropped by the filter. It is rule-based text matching, not AI, so it can miss unusual wording; every flag carries the sentence it came from in `evidence`. Jobs without a description (for example Lever or Workday with `includeDescription: false`) get `workAuthorization: null` and are never dropped. Greenhouse descriptions are always read, so Greenhouse jobs are flagged even with descriptions turned off.

**Is it legal?** It reads public job-board data that companies publish for job seekers and aggregators through official public APIs. No login. Follow the terms of the sites you use and local law. Our Actors are ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract what the user has chosen to share publicly. However, your results could contain personal data, which is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

**Found a bug or need a field?** Open an issue in the **Issues** tab and I'll usually reply within a day.

If it saved you time, a quick review on the Store helps a solo developer keep improving it. Bugs or ideas? Open an Issue.

# Actor input Schema

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

One per line. Board URLs: boards.greenhouse.io/stripe, job-boards.greenhouse.io/airbnb, jobs.lever.co/spotify, jobs.ashbyhq.com/ramp, apply.workable.com/<company>, jobs.smartrecruiters.com/<Company>, <company>.recruitee.com, <company>.jobs.personio.de, and Workday career sites like https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite. Single job links work too. Bare slugs ("stripe", "ramp") are auto-detected across Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee and Personio (Workday needs the full careers-site URL). Other careers-page URLs (e.g. https://ramp.com/careers) are scanned for an embedded ATS board.

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

Keep jobs whose title contains ANY of these (case-insensitive), e.g. "frontend", "react", "data engineer". Empty = all jobs.

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

Drop jobs whose title contains any of these, e.g. "senior", "manager", "intern".

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

Keep jobs whose location (any of them) contains ANY of these, e.g. "New York", "United States", "London", "Remote".

## `remoteOnly` (type: `boolean`):

Keep only jobs flagged remote by the ATS or with "Remote" in the location.

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

Keep jobs whose department or team contains ANY of these, e.g. "Engineering", "Design", "Sales".

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

Keep only jobs first published in the last N days. 0 = any age.

## `excludeNoSponsorship` (type: `boolean`):

Drops jobs whose description says visa sponsorship is not offered (e.g. "unable to sponsor", "not eligible for immigration sponsorship", "without current or future visa sponsorship"). Dropped jobs are not charged. Jobs without a description are kept. Every job also gets a <code>workAuthorization</code> field (sponsorship, usCitizenshipRequired, usPersonRequired, exportControlled, securityClearance) with the sentence each flag came from. Rule-based text matching, not AI: check the evidence before relying on it.

## `excludeCitizenshipOrClearance` (type: `boolean`):

Drops jobs whose description requires US citizenship, US-person status for export control (ITAR: citizen or green card), or a security clearance (active or obtainable: Secret, TS/SCI, public trust, any country). Jobs where clearance is only 'beneficial' or 'preferred' are kept. Dropped jobs are not charged.

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

Stop after this many matching jobs per company. 0 = no limit.

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

Add the full description as plain text and Markdown (great for LLMs and AI agents). Turn off for a faster, smaller list.

## `includeHtml` (type: `boolean`):

Also save the original description HTML.

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

Remember every job this Actor has returned and, on later runs, output only jobs it hasn't returned before. Perfect for a daily schedule that alerts you to new openings. The first run returns everything and saves the baseline. You only pay for new jobs. Memory is kept in your account's key-value store "ats-jobs-scraper-state".

## `stateKey` (type: `string`):

Name for the "only new jobs" memory, e.g. "frontend-alerts". Runs with the same name share one memory. Leave empty to use one memory per company list (same companies, any order = same memory). Letters, numbers, - \_ . only.

## `atsToTry` (type: `array`):

For bare company slugs, which ATSs to try, in order. Default: all seven (Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Recruitee, Personio). Workday can't be guessed from a slug; paste its careers-site URL instead.

## `detectFromCareerPage` (type: `boolean`):

For URLs that aren't an ATS board (e.g. https://ramp.com/careers), load the page once and look for a linked or embedded Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio or Workday board.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/stripe",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/ramp",
    "notion"
  ],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "excludeNoSponsorship": false,
  "excludeCitizenshipOrClearance": false,
  "maxJobsPerCompany": 50,
  "includeDescription": true,
  "includeHtml": false,
  "onlyNewJobs": false,
  "detectFromCareerPage": true
}
```

# Actor output Schema

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

No description

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

No description

# 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://boards.greenhouse.io/stripe",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/ramp",
        "notion"
    ],
    "maxJobsPerCompany": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("chimey_forearm/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://boards.greenhouse.io/stripe",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/ramp",
        "notion",
    ],
    "maxJobsPerCompany": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("chimey_forearm/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://boards.greenhouse.io/stripe",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/ramp",
    "notion"
  ],
  "maxJobsPerCompany": 50
}' |
apify call chimey_forearm/ats-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chimey_forearm/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/dxqCOXgcKeo6Os5nh/builds/XJsnGUSueOJI15P5t/openapi.json
