# ATS Job Scraper & Monitor — Greenhouse, Lever, Ashby +3 (`vertaizen/ats-hiring-signals`) Actor

ATS job scraper for Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee & Workable. Point it at any company list and get clean job postings. Monitor mode returns only NEW jobs — hiring signals for sales prospecting & recruiting intel. Pay per result, no proxies, MCP-ready.

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

## Pricing

from $2.00 / 1,000 job postings

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 Job Scraper — Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee & Workable

This **ATS job scraper** extracts live job postings directly from the public job boards of **Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable** — no browser, no proxies, no LinkedIn scraping. Point it at any list of companies and get clean, structured **hiring data** in seconds. Turn on **monitor mode** and it becomes a **job posting monitor**: scheduled runs return only the postings that appeared since the last run — instant **hiring signals** for sales prospecting, recruiting intelligence and market research.

Most "job scrapers" fight anti-bot walls on LinkedIn or Indeed and break weekly. This one reads the **same structured JSON endpoints that power each company's own careers page**, so it stays fresh, fast and unblocked — and it captures jobs *before* they ever reach the aggregators.

### Why scrape ATS job boards directly (vs. a LinkedIn or Indeed scraper)?

You don't compete for the generic term "job scraper" — you get the data at its **source**, cleaner and earlier. Here is how a direct ATS scraper compares to the usual alternatives:

| | **This ATS Job Scraper** | LinkedIn / Indeed scrapers | Manual careers-page checking |
|---|---|---|---|
| Data freshness | Postings appear here **first**, before aggregators | Delayed by the aggregator's own crawl | Real-time but per-page, by hand |
| Reliability | Public JSON endpoints — no anti-bot walls | Constant CAPTCHAs, IP blocks, layout breaks | Reliable but not scalable |
| Structured output | Clean JSON (title, dept, location, URL, date) | Often HTML fragments needing cleanup | Copy-paste |
| Monitor mode (only NEW jobs) | ✅ Built in | ❌ Rare | ❌ |
| Proxies required | ❌ None | ✅ Usually | — |
| Hiring-signal use for sales | ✅ Purpose-built | Possible but noisy | Not practical at scale |

- **Fresher than job aggregators** — postings appear on the ATS before they reach Indeed or LinkedIn.
- **Stable and reliable** — these are public JSON endpoints, not fragile HTML scraping.
- **Hiring = a buying signal.** A company hiring a "Salesforce Administrator" is buying Salesforce tooling. A company hiring 5 SDRs is scaling sales. Sales teams use this data to time outreach.
- **AI-agent ready** — flat input, clean JSON output. Works out of the box via MCP for AI agents and LLM pipelines.

### What you get for each job posting

```json
{
  "company": "stripe",
  "ats": "greenhouse",
  "jobId": "gh-7954688",
  "title": "Account Executive, AI Sales",
  "department": "AI GTM Strategy & Solutions",
  "location": "San Francisco, CA",
  "url": "https://stripe.com/jobs/search?gh_jid=7954688",
  "publishedAt": "2026-06-02T08:58:57-04:00",
  "isNew": true,
  "matchedKeywords": ["sales"]
}
```

### How to use it

1. **Add companies** — as plain slugs (`stripe`), explicit pairs (`lever:haus`), or careers-page URLs (`https://boards.greenhouse.io/airbnb`). The ATS is auto-detected.
2. **(Optional) Add keywords** — only jobs matching your keywords (title, department or description) are returned.
3. **(Optional) Enable monitor mode** — and schedule the actor (e.g. daily). Each run returns only NEW postings per company. Combine with a webhook to push new jobs to Slack, email or your CRM.

### Use cases

Each of these is a real job-to-be-done buyers search for:

- **"Get hiring signals for sales prospecting"** — monitor your target-account list and let a new "Head of RevOps" or "5 new SDRs" req trigger perfectly timed outreach while budget is fresh.
- **"Track competitor hiring by department"** — watch a rival's Greenhouse or Lever board and see exactly where they're investing (AI, sales, EMEA expansion) before it's public.
- **"Scrape startup jobs for a niche job board"** — pull fresh "remote React roles at Series-A startups" straight from ATS boards to power a talent community or newsletter.
- **"Measure hiring velocity for investment research"** — headcount growth per company as a leading indicator for VC and PE diligence.
- **"Feed hiring data to an AI agent"** — pipe structured postings into an LLM workflow via the Apify MCP server for enrichment and scoring.

#### Hiring signals for sales prospecting

The highest-value use of this actor. Point it at your ICP account list in monitor mode, filter by keyword (e.g. `Salesforce`, `RevOps`, `SDR`, `data engineer`), and every scheduled run hands your SDRs a shortlist of accounts that just started spending in your category — the single strongest timing signal in B2B outbound.

### Pricing

Pay per job posting delivered — no subscription, no minimum. You only pay for results. Companies that can't be found are never charged.

### FAQ

#### Which ATS platforms are supported?

Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable. These cover the large majority of startup and mid-market job boards. Missing one you need? Open an issue and it will be added. You can confirm any board's public API in the vendor docs, e.g. the [Greenhouse Job Board API](https://developers.greenhouse.io/job-board.html) and the [Lever Postings API](https://github.com/lever/postings-api).

#### How is this different from a LinkedIn jobs scraper?

A LinkedIn or Indeed scraper reads an aggregator that itself copied the job from the company's ATS — so it's slower, noisier, and constantly fighting anti-bot systems. This actor reads the ATS **directly**: fresher data, clean JSON, no proxies, and no blocking.

#### Can I use hiring data for sales prospecting?

Yes — that's the primary use case. Job postings are public business signals, not personal data. A new "Salesforce Admin" or "5 SDRs" req tells you a company is investing in a category *right now*, which is exactly when outreach converts best.

#### Is scraping job boards legal?

The actor only reads the same public JSON endpoints that power each company's own careers page. No login, no personal data, no rate-limit abuse. As always, review each site's terms and your local regulations for your specific use case.

#### How does monitor mode work?

The actor keeps a per-company record of previously seen job IDs in a persistent store. On each run it compares current postings against that record and outputs only new ones (`isNew: true`). The first run establishes the baseline.

#### How do I get Slack or email alerts for new postings?

Enable `monitorMode`, schedule the actor (e.g. daily), and attach an Apify [webhook or integration](https://docs.apify.com/platform/integrations) (Slack, email, Zapier, Make) to the run-succeeded event. Every new posting is pushed the moment it appears.

#### How do I find a company's slug?

Usually it's the company name in lowercase (e.g. `stripe`). If unsure, paste the careers-page URL and the actor extracts the slug and detects the ATS automatically.

#### Can AI agents use this actor?

Yes — the input schema is flat and agent-friendly, and every Apify actor is consumable via the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so agents can call it as a tool.

#### What happens if a company isn't found?

You are never charged for it. The company is listed in the `NOT_FOUND` record of the run's key-value store and in the run log, and the rest of your list continues processing normally.

# Actor input Schema

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

Company slugs, `ats:slug` pairs, or careers-page URLs. Examples: `stripe`, `lever:netflix`, `https://boards.greenhouse.io/airbnb`. The ATS is auto-detected when not specified.

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

Only return jobs whose title, department or description contains at least one of these keywords (case-insensitive). Leave empty to return all jobs.

## `monitorMode` (type: `boolean`):

When enabled, the actor remembers previously seen postings per company and only outputs jobs that appeared since the last run. Ideal for scheduled runs (hiring signals, alerts).

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

Safety cap on the number of postings returned per company.

## Actor input object example

```json
{
  "companies": [
    "stripe",
    "notion",
    "figma"
  ],
  "keywords": [],
  "monitorMode": false,
  "maxJobsPerCompany": 500
}
```

# 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": [
        "stripe",
        "notion",
        "figma"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("vertaizen/ats-hiring-signals").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": [
        "stripe",
        "notion",
        "figma",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("vertaizen/ats-hiring-signals").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": [
    "stripe",
    "notion",
    "figma"
  ]
}' |
apify call vertaizen/ats-hiring-signals --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/BCraLTCKQgzuV1QpR/builds/CfNlla0ezBoqD19Uf/openapi.json
