# Greenhouse, Ashby & Lever Jobs Scraper API (B2B Hiring Signals) (`ramgoxxx/greenhouse-ashby-lever-jobs-scraper`) Actor

Scrape live job postings, salary bands & B2B hiring signals from Greenhouse, Ashby & Lever in one unified schema ($0.80/1K). MCP & n8n ready.

- **URL**: https://apify.com/ramgoxxx/greenhouse-ashby-lever-jobs-scraper.md
- **Developed by:** [Antonio Ramos Gómez](https://apify.com/ramgoxxx) (community)
- **Categories:** Jobs, Lead generation, Agents
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.80 / 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/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, Ashby & Lever Jobs Scraper API do?

**Greenhouse, Ashby & Lever Jobs Scraper API** is an enterprise-grade B2B hiring intelligence and job board aggregator. It scrapes live job postings, salary bands, departments, workplace arrangements (Remote/Hybrid/On-site), and direct application URLs across the three dominant applicant tracking systems (ATS) used by tech scaleups, AI unicorns, and Fortune 500 enterprises:

- **Greenhouse** (`boards.greenhouse.io/<company>`) — Stripe, Figma, Airbnb, Discord, Databricks, DoorDash, Pinterest, Gitlab.
- **Ashby** (`jobs.ashbyhq.com/<company>`) — Linear, Cursor (Anysphere), Perplexity, Ramp, Vercel, Supabase, Retool.
- **Lever** (`jobs.lever.co/<company>`) — Zoox, Mistral AI, Spotify, Netflix, Palantir, Kraken.

Instead of paying for three separate scrapers or dealing with slow, brittle headless browsers, this Actor connects directly to public ATS endpoints. You get structured, normalized hiring signals in seconds at just **$0.80 per 1,000 job postings** with zero start fee.

***

### Why scrape B2B hiring signals from ATS boards?

Job postings are among the highest-intent corporate buying signals available:

1. **B2B Sales Triggers & Account Prospecting**: When a target enterprise opens 10+ listings for *“Data Engineer”* or *“AI Researcher”*, they are actively allocating budget for cloud compute, data warehousing, and AI tooling.
2. **Niche & AI Job Boards**: Power curated job directories (e.g., *“Remote AI Jobs”*, *“Y Combinator Startup Careers”*, *“Web3 Opportunities”*) with automated daily syncs.
3. **Salary & Compensation Benchmarking**: Track real-time base salaries and equity bands published under pay-transparency laws (NYC, California, Colorado, EU).
4. **Competitor Growth & Attrition Monitoring**: Detect when competitors scale up their sales team or downsize specific departments.
5. **Headhunter & Recruiter Lead Generation**: Spot companies experiencing rapid headcount growth before recruiters on LinkedIn do.

***

### Key Features & Comparison

| Feature | This Actor (`ramgoxxx`) | Fragmented Single-ATS Scrapers | Headless Browser Crawlers |
| :--- | :--- | :--- | :--- |
| **Supported ATS Platforms** | **Greenhouse + Ashby + Lever** | Only 1 platform per actor | Inconsistent |
| **Pricing Model** | **$0.80 / 1,000 jobs (Pay-Per-Event)** | $1.50 – $3.00 / 1,000 jobs | High compute usage ($/GB) |
| **Free Tier Allowance** | **6,250 free jobs / month** | 1,000 – 2,000 jobs | Consumes compute fast |
| **Extraction Speed** | **Direct API (<3 seconds / board)** | Varies | Slow (15–45s per page) |
| **Schema Normalization** | **Unified single JSON schema** | Fragmented per ATS | Requires custom parsing |
| **Compensation / Salary Bands** | **Extracted & parsed** | Often missing | Unreliable regex |
| **AI & MCP Agent Ready** | **Yes (`mcp.apify.com`)** | Rarely supported | No |
| **n8n / Make.com Webhooks** | **Native Apify Integration** | Manual setup | Manual setup |

***

### Pay-Per-Event Pricing Math ($5.00 Free Tier)

This Actor uses Apify’s **Pay-Per-Event (PPE)** pricing model. You only pay for the actual job listings returned in your dataset. Platform compute usage is **100% FREE**.

- **Price per job posting**: **$0.0008** (`$0.80 / 1,000 jobs`)
- **Apify Free Tier ($5.00 / month)**: Extract up to **6,250 live job postings every single month at $0.00 net cost**.
- **10,000 jobs**: Only `$8.00`
- **50,000 jobs**: Only `$40.00`

***

### Input Parameters

| Field | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `companies` | `Array<Object>` | `[{"platform": "greenhouse", "boardToken": "stripe"}, {"platform": "ashby", "boardToken": "linear"}]` | Array of company targets with `platform` (`greenhouse`, `ashby`, or `lever`) and company slug. |
| `quickTokens` | `Array<String>` | `[]` | Simple list of company slugs (e.g. `["stripe", "linear", "zoox"]`) scraped using `defaultPlatform`. |
| `defaultPlatform` | `String` | `"greenhouse"` | ATS engine used for `quickTokens` (`greenhouse`, `ashby`, `lever`, or `auto_detect`). |
| `departmentFilter` | `String` | `""` | Case-insensitive keyword filter for department or team (e.g. `"Engineering"`, `"Sales"`, `"Product"`). |
| `locationFilter` | `String` | `""` | Filter by city, state, or workplace arrangement (e.g. `"Remote"`, `"London"`, `"San Francisco"`). |
| `maxJobsPerCompany` | `Integer` | `50` | Maximum job postings to extract per target company board (1 to 500). |
| `includeDescription`| `Boolean` | `true` | Extract clean, plain-text job descriptions and candidate requirements. |
| `proxyConfiguration`| `Object` | `{ "useApifyProxy": false }` | Optional Apify Proxy fallback for rate-limited corporate networks. |

***

### Output Dataset Schema

Every extracted job posting is standardized into a unified JSON structure:

| Field Name | Type | Description | Example |
| :--- | :--- | :--- | :--- |
| `atsPlatform` | String | ATS source engine | `"greenhouse"`, `"ashby"`, or `"lever"` |
| `company` | String | Target company slug or board token | `"stripe"`, `"linear"`, `"zoox"` |
| `jobId` | String | Unique requisition identifier | `"8172487"` |
| `title` | String | Official job title | `"Senior Staff Machine Learning Engineer"` |
| `location` | String | Location or city/country | `"San Francisco, CA"`, `"Europe"`, `"Remote"` |
| `workplaceType` | String | Workplace classification | `"Remote"`, `"Hybrid"`, `"On-site"` |
| `department` | String | Primary department or organization | `"Engineering"`, `"Product"`, `"Security Analytics"` |
| `team` | String | Sub-team or specialty unit | `"Core Platform"`, `"Growth Infrastructure"` |
| `employmentType` | String | Full-time, contract, or internship | `"Full-time"` |
| `publishedAt` | String | First published timestamp | `"2026-10-29T10:42:09-04:00"` |
| `updatedAt` | String | Last modified timestamp | `"2026-11-02T14:15:00-04:00"` |
| `url` | String | Canonical job board URL | `"https://jobs.ashbyhq.com/linear/d3bc1ced-..."` |
| `applyUrl` | String | Direct candidate application link | `"https://stripe.com/jobs/search?gh_jid=8172487"` |
| `compensation` | String | Extracted salary range or total comp | `"$185,000 - $240,000 USD + Equity"` |
| `descriptionText`| String | Cleaned, plain-text job overview | `"About the team: We are looking for an engineer..."` |

***

### Integration Code Examples

#### 1. Python SDK (`apify-client`)

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run_input = {
    "companies": [
        {"platform": "greenhouse", "boardToken": "stripe"},
        {"platform": "ashby", "boardToken": "linear"},
        {"platform": "lever", "boardToken": "zoox"}
    ],
    "departmentFilter": "Engineering",
    "locationFilter": "Remote",
    "maxJobsPerCompany": 50,
    "includeDescription": True
}

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

## Fetch all extracted job postings
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"[{item['atsPlatform'].upper()}] {item['company']} - {item['title']} ({item['location']})")
    if item['compensation']:
        print(f"  Compensation: {item['compensation']}")
    print(f"  Apply: {item['applyUrl']}")
```

#### 2. Node.js / TypeScript (`apify-client`)

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

async function scrapeHiringSignals() {
  const run = await client.actor('ramgoxxx/greenhouse-ashby-lever-jobs-scraper').call({
    companies: [
      { platform: 'ashby', boardToken: 'linear' },
      { platform: 'greenhouse', boardToken: 'figma' }
    ],
    maxJobsPerCompany: 100
  });

  const { items } = await client.dataset(run.defaultDatasetId).listItems();
  console.log(`Extracted ${items.length} jobs.`);
}

scrapeHiringSignals();
```

#### 3. cURL & Direct REST API

```bash
curl -X POST "https://api.apify.com/v2/acts/ramgoxxx~greenhouse-ashby-lever-jobs-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companies": [
      {"platform": "ashby", "boardToken": "perplexity"},
      {"platform": "greenhouse", "boardToken": "databricks"}
    ],
    "maxJobsPerCompany": 25
  }'
```

***

### Model Context Protocol (MCP) & AI Agent Integration

This Actor connects directly with Claude Desktop, Cursor, and any MCP-compliant autonomous AI agents via [Apify MCP](https://mcp.apify.com).

Add to your `claude_desktop_config.json` or `cursor_mcp.json`:

```json
{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/mcp-server"],
      "env": {
        "APIFY_TOKEN": "YOUR_APIFY_TOKEN"
      }
    }
  }
}
```

Now prompt Claude or your autonomous agent directly:

> *"Use Apify to check current AI engineering job openings at Linear and Stripe. Return titles, remote status, and salary ranges."*

***

### n8n & Make.com Automation Workflows

Automate B2B lead generation without writing code:

1. **Trigger**: Schedule trigger (e.g., every Monday at 08:00 AM).
2. **Apify Node**: Select `Run Actor` -> `ramgoxxx/greenhouse-ashby-lever-jobs-scraper`.
3. **Input JSON**: Pass list of target enterprise accounts.
4. **Filter Node**: Filter for new roles containing *"Head of"*, *"Director"*, or *"Founding Engineer"*.
5. **Slack / CRM Action**: Post hot hiring signals to `#sales-triggers` or update HubSpot/Salesforce accounts.

***

### Frequently Asked Questions (FAQ)

#### How do I find a company's board token or slug?

Look at the URL of the company's career page:

- **Greenhouse**: `boards.greenhouse.io/{boardToken}` or `job-boards.greenhouse.io/{boardToken}`. (Example: `boards.greenhouse.io/stripe` -> `stripe`).
- **Ashby**: `jobs.ashbyhq.com/{boardToken}`. (Example: `jobs.ashbyhq.com/linear` -> `linear`).
- **Lever**: `jobs.lever.co/{boardToken}`. (Example: `jobs.lever.co/zoox` -> `zoox`).

#### Can I scrape multiple ATS engines in a single run?

Yes. Simply pass companies using different platforms in the `companies` list. The Actor normalizes all records into the same standardized schema.

#### How often are job postings updated?

The Actor queries public ATS endpoints in real time. Whenever a company publishes, edits, or closes a position on their ATS, your next run reflects that change immediately.

#### Are full job descriptions included?

Yes. By default (`includeDescription: true`), the Actor cleans HTML tags, strips boilerplate headers, and returns clean plain-text job descriptions ready for LLM summarization, semantic search, or vector embedding.

***

### Compliance, Terms & GDPR Notice

This Actor extracts exclusively publicly available job vacancy information published by employers for public recruitment. It does not collect private personal employee data, bypass authentication or CAPTCHAs, or scrape password-protected internal portals. When utilizing extracted job data, users must adhere to applicable local regulations, employment law, and GDPR guidelines regarding personal candidate contacts.

# Actor input Schema

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

List of company job boards to scrape. Specify the ATS platform ('greenhouse', 'ashby', or 'lever') and the company board token or subdomain.

## `quickTokens` (type: `array`):

Quick list of company slugs (e.g. \['stripe', 'openai', 'linear']). Scraped using the default platform selected below.

## `defaultPlatform` (type: `string`):

ATS engine used for tokens in the quick list or when platform is unspecified.

## `departmentFilter` (type: `string`):

Only return jobs whose department or team contains this keyword (case-insensitive, e.g. 'Engineering', 'Product', 'Sales').

## `locationFilter` (type: `string`):

Only return jobs whose location or workplace type contains this keyword (e.g. 'Remote', 'Europe', 'San Francisco').

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

Maximum job postings to extract per target company board.

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

Extract cleaned plain-text job descriptions and responsibilities.

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

Optional Apify Proxy fallback for rate-limited corporate networks.

## Actor input object example

```json
{
  "companies": [
    {
      "platform": "greenhouse",
      "boardToken": "stripe"
    },
    {
      "platform": "ashby",
      "boardToken": "linear"
    }
  ],
  "quickTokens": [],
  "defaultPlatform": "greenhouse",
  "departmentFilter": "",
  "locationFilter": "",
  "maxJobsPerCompany": 50,
  "includeDescription": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Structured job postings with department, location, compensation & apply links.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("ramgoxxx/greenhouse-ashby-lever-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("ramgoxxx/greenhouse-ashby-lever-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 '{}' |
apify call ramgoxxx/greenhouse-ashby-lever-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ramgoxxx/greenhouse-ashby-lever-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/2NIdze2Z3u2cSWfam/builds/lXvkW2S8XacP55HR9/openapi.json
