# ATS Jobs Scraper — Hiring Signals & Alerts (5 ATS, Auto-Detect) (`nicolas_izquierdo/ats-jobs-scraper`) Actor

Track hiring at your target companies. Live jobs from Greenhouse, Lever, Ashby, SmartRecruiters & Recruitee with auto-detection, unified schema, diff mode (only NEW jobs — ideal for scheduled alerts), salary data and per-company hiring signals for B2B sales. No login, no proxies.

- **URL**: https://apify.com/nicolas\_izquierdo/ats-jobs-scraper.md
- **Developed by:** [Nicolas Izquierdo](https://apify.com/nicolas_izquierdo) (community)
- **Categories:** Jobs, Automation, Lead generation
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## ATS Jobs Scraper — Track Hiring at Your Target Companies (5 ATS Platforms)

**Give it a list of companies. Get back live job postings, new-role alerts and per-company hiring signals.**

Most job-data actors are built for *job search*: you type a query and get matching jobs from everywhere. This Actor is built for the opposite, **company-first** workflow: you already know which companies you care about — target accounts, competitors, portfolio companies, dream employers — and you want to know **what they're hiring for and when that changes**.

Public data only: it reads the official public job-board APIs of **Greenhouse, Lever, Ashby, SmartRecruiters and Recruitee** — the endpoints companies publish on purpose. **No login, no cookies, no proxies, no anti-bot games.** That makes it fast, cheap and reliable.

| ATS | Typical companies | Board URL formats accepted |
|---|---|---|
| Greenhouse | US tech, unicorns | `boards.greenhouse.io/X`, `job-boards.greenhouse.io/X` |
| Lever | VC-backed startups & scale-ups | `jobs.lever.co/X` |
| Ashby | High-growth startups | `jobs.ashbyhq.com/X` |
| SmartRecruiters | Enterprise & mid-market | `jobs.smartrecruiters.com/X`, `careers.smartrecruiters.com/X` |
| Recruitee | European SMB & scale-ups | `X.recruitee.com` |

### What can it do?

- **Auto-detect the ATS** from a company slug, board URL or website domain — one input format for all three platforms
- **One normalized schema** across Greenhouse, Lever and Ashby: title, department, team, locations, remote flag, employment type, numeric salary, dates, apply URLs
- **Diff mode (`newJobsOnly`)**: run it on a schedule and only get postings that weren't there last time — the foundation for hiring alerts via webhooks, Slack or Make/Zapier
- **`isNew` flag** on every job, tracked across runs per company
- **Hiring signals per company**: total openings, department breakdown, remote share, newest posting date — companies expanding a department are your best B2B buying signal
- **Server-side filters** so you only pay for what you need: keyword, department, location, remote-only, posted-in-last-N-days
- **Normalized compensation**: `compensationMin` / `compensationMax` / `compensationCurrency` parsed from disclosed salary data
- Export as JSON, CSV or Excel; run via API; schedule with webhooks; MCP-ready for AI agents

### Use cases

| Who | What |
|---|---|
| B2B sales teams | Monitor target accounts: a company hiring 5 SDRs is buying sales tooling *this quarter*. Feed `hiring_signals` into your CRM. |
| Recruiters & sourcers | Track competitor hiring, spot which teams are growing, be first on new reqs. |
| Job seekers | Watch your 20 dream companies daily with `newJobsOnly` and apply within hours, not weeks. |
| VCs & analysts | Hiring velocity per portfolio/sector without waiting for quarterly updates. |
| Niche job boards | Curated boards (remote-only, by city, by stack) fed from companies you hand-pick. |

### Input

```json
{
    "companies": [
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/linear",
        "stripe",
        "datadog@greenhouse"
    ],
    "keywords": ["engineer"],
    "remoteOnly": false,
    "newJobsOnly": false,
    "computeSignals": true
}
```

| Parameter | Type | Description |
|---|---|---|
| `companies` | Array (required) | Board URLs (`boards.greenhouse.io/X`, `job-boards.greenhouse.io/X`, `jobs.lever.co/X`, `jobs.ashbyhq.com/X`), plain slugs (`stripe` — ATS auto-detected), `slug@ats`, or company domains (`linear.app`). |
| `keywords` | Array | Only jobs whose title/department matches any keyword (case-insensitive). |
| `departments` | Array | Filter by department/team substring. |
| `locations` | Array | Filter by location substring (`london`, `remote`, `us`...). |
| `remoteOnly` | Boolean | Only remote roles. |
| `postedAfterDays` | Integer | Only roles posted in the last N days (where the ATS provides dates). |
| `newJobsOnly` | Boolean | **Diff mode.** Only return jobs not seen in previous runs. First run primes the memory. |
| `trackNewJobs` | Boolean | Adds `isNew` to every job (default true). |
| `includeDescription` | Boolean | Include full plain-text description (bigger items). |
| `computeSignals` | Boolean | Push one `hiring_signals` summary item per company (default true). |
| `maxJobsPerCompany` | Integer | Safety cap per company (default 2000). |

### Output

One item per job:

```json
{
    "type": "job",
    "source": "ashby",
    "company": "linear",
    "title": "Product Engineer",
    "department": "Engineering",
    "team": "Product",
    "location": "North America",
    "allLocations": ["North America", "Europe"],
    "isRemote": true,
    "employmentType": "FullTime",
    "compensationRaw": "$140K – $180K",
    "compensationMin": 140000,
    "compensationMax": 180000,
    "compensationCurrency": "USD",
    "publishedAt": "2026-06-25T00:00:00.000Z",
    "isNew": true,
    "url": "https://jobs.ashbyhq.com/linear/...",
    "applyUrl": "https://jobs.ashbyhq.com/linear/.../application",
    "scrapedAt": "2026-07-07T18:00:00.000Z"
}
```

Plus one `hiring_signals` item per company (optional):

```json
{
    "type": "hiring_signals",
    "company": "linear",
    "totalOpenings": 42,
    "remoteOpenings": 30,
    "remoteShare": 0.71,
    "topDepartments": [{ "name": "Engineering", "count": 25 }],
    "topLocations": [{ "name": "North America", "count": 28 }],
    "newestPostingAt": "2026-07-01T00:00:00.000Z"
}
```

### Quick-start recipes

**Daily hiring alerts on your target accounts** — schedule daily, add a webhook/Slack integration:

```json
{ "companies": ["stripe", "https://jobs.ashbyhq.com/linear", "datadog@greenhouse"], "newJobsOnly": true }
```

**Remote engineering roles at hand-picked companies:**

```json
{ "companies": ["https://jobs.lever.co/palantir", "linear.app"], "keywords": ["engineer"], "remoteOnly": true }
```

**Sales-intel snapshot (signals only, minimal cost):**

```json
{ "companies": ["stripe", "linear.app", "palantir@lever"], "keywords": ["sales", "account executive", "sdr"], "computeSignals": true }
```

### FAQ

**Is it legal to scrape these job boards?** This Actor only reads the official public job-board APIs that Greenhouse, Lever and Ashby document and expose specifically so postings can be shared. No authentication is bypassed and no personal data is collected.

**How is this different from job-search APIs like the big 75-ATS aggregators?** Those are *query-first* (great for job boards: "find all Software Engineer jobs anywhere"). This Actor is *company-first*: it always reflects the live board of the exact companies you specify — no index lag, no coverage gaps for small companies, and per-company diffing and signals that query-first tools don't give you.

**A company isn't found — why?** It may use a different ATS (Workday, Workable, BambooHR...) or a non-obvious slug. Try passing the exact board URL. More ATS platforms are on the roadmap — open an Issue to vote.

**How fresh is the data?** It's read live from the company's board at run time — zero indexing delay, no ghost jobs.

**How does diff mode behave on the first run?** It returns everything and primes the per-company memory; from the second run on, only new postings.

### Changelog

**1.2**

- Two new ATS platforms: **SmartRecruiters** (enterprise/mid-market, with pagination) and **Recruitee** (European SMB), both auto-detected
- `experienceLevel` field where the ATS provides it

**1.1**

- Diff mode (`newJobsOnly`) with cross-run memory and `isNew` flag on every job
- Normalized compensation fields: `compensationMin` / `compensationMax` / `compensationCurrency`
- Hiring-signals items now render cleanly in the table view

**1.0**

- Initial release: Greenhouse + Lever + Ashby, ATS auto-detection, unified schema, filters, hiring signals

# Actor input Schema

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

List of companies to scrape. Each item can be: a board URL (e.g. `https://boards.greenhouse.io/stripe`, `https://jobs.lever.co/palantir`, `https://jobs.ashbyhq.com/linear`, `https://jobs.smartrecruiters.com/bosch`, `https://acme.recruitee.com`), a plain slug (e.g. `stripe`) — the ATS will be auto-detected across all 5 platforms — or `slug@ats` (e.g. `palantir@lever`) to skip detection.

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

Only include jobs whose title or department matches at least one keyword (case-insensitive). Leave empty to include all jobs.

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

Only include jobs from these departments/teams (case-insensitive substring match).

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

Only include jobs in these locations (case-insensitive substring match, e.g. `london`, `remote`, `us`).

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

Only include jobs marked as remote or with 'remote' in their location.

## `postedAfterDays` (type: `integer`):

Only include jobs published in the last N days (where the ATS provides a date). Leave empty for all.

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

Include the plain-text job description in each result. Increases item size.

## `newJobsOnly` (type: `boolean`):

Only return jobs not seen in previous runs. Perfect for scheduled monitoring: run daily on your target-account list and get alerted (via webhook/integration) only when a company posts new roles. The first run returns everything and primes the memory.

## `trackNewJobs` (type: `boolean`):

Adds an `isNew` field to every job (true if not seen in previous runs). Disable to skip cross-run tracking entirely.

## `computeSignals` (type: `boolean`):

Push one extra summary item per company with hiring signals: total openings, breakdown by department, remote share, newest posting date and top locations. Great for B2B prospecting and market research.

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

Safety cap of job items scraped per company.

## Actor input object example

```json
{
  "companies": [
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/linear"
  ],
  "remoteOnly": false,
  "includeDescription": false,
  "newJobsOnly": false,
  "trackNewJobs": true,
  "computeSignals": true,
  "maxJobsPerCompany": 2000
}
```

# 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://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/linear"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nicolas_izquierdo/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://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/linear",
    ] }

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

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/linear"
  ]
}' |
apify call nicolas_izquierdo/ats-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=nicolas_izquierdo/ats-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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