# Job Postings Scraper — Greenhouse, Lever, Ashby, Workable (`sturdydata/job-postings-scraper`) Actor

Scrape live job postings straight from company career boards (Greenhouse, Lever, Ashby, Workable, Recruitee) using their stable public JSON APIs — not fragile HTML. One unified schema across all five ATS providers: title, location, remote flag, department, compensation (where published), apply UR...

- **URL**: https://apify.com/sturdydata/job-postings-scraper.md
- **Developed by:** [Sturdy Data](https://apify.com/sturdydata) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Job Postings Scraper — Greenhouse, Lever, Ashby, Workable, Recruitee

Scrape live job postings **straight from company career boards** — via each ATS provider's stable, public JSON API. Not LinkedIn HTML that breaks every month. One unified schema across all five providers.

Built for: recruiting intelligence, hiring-signal lead generation ("who is hiring SDRs right now?"), job aggregators, market/comp research.

### Why this scraper

LinkedIn and Indeed scrapers are the lowest-rated job actors on the store — they fight anti-bot walls and silently miss records, apply URLs, and fields. This actor goes to the **source**: the ATS boards companies actually publish to. Those JSON endpoints are versioned public APIs that have been stable for years.

- **Five ATS providers, one schema.** Greenhouse, Lever, Ashby, Workable, Recruitee.
- **Apply URL always included** — it's the canonical posting URL from the ATS itself.
- **Compensation captured where published** (Lever salary ranges, Ashby compensation tiers).
- **No proxies needed, no anti-bot roulette** — near-100% success rate by construction.
- Per-board run summary (`RUN_SUMMARY` in the key-value store) tells you exactly which boards succeeded, how many jobs each returned, and any errors. No silent failures.
- **robots.txt respected.** SmartRecruiters is intentionally not supported — its robots.txt blocks all crawlers except LinkedInBot, so we leave it alone.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `boardUrls` | array | — | Career board URLs, one per company (see formats below). Shorthand `provider:company` also works. |
| `includeDescription` | boolean | `true` | Full plain-text description per posting. |
| `maxJobsPerBoard` | integer | `500` | Safety cap per company. |

Supported URL formats:

````

https://boards.greenhouse.io/<company>      or  greenhouse:<company>
https://jobs.lever.co/<company>             or  lever:<company>
https://jobs.ashbyhq.com/<company>          or  ashby:<company>
https://apply.workable.com/<company>        or  workable:<company>
https://<company>.recruitee.com             or  recruitee:<company>

````

```json
{
    "boardUrls": ["https://boards.greenhouse.io/gitlab", "lever:spotify", "ashby:openai"],
    "includeDescription": true
}
````

### Output schema

One dataset item per job posting:

```json
{
    "source": "lever",
    "company": "spotify",
    "companyName": null,
    "id": "5c2a4bb4-cb46-4c39-...",
    "title": "Backend Engineer, Podcast Platform",
    "url": "https://jobs.lever.co/spotify/5c2a4bb4-...",
    "location": "Stockholm, Sweden",
    "secondaryLocations": ["London, UK"],
    "remote": false,
    "department": "Engineering",
    "team": "Podcast Mission",
    "employmentType": "Full-time",
    "compensation": "90000-120000 EUR per-year-salary",
    "publishedAt": "2026-06-12T09:31:00.000Z",
    "updatedAt": null,
    "description": "Spotify is looking for ... (plain text)",
    "scrapedAt": "2026-07-04T10:00:00.000Z"
}
```

Fields that a provider does not publish are `null` — never guessed. `remote` is `true`/`false` when the ATS states it, `null` when unknown.

### Pricing

**Pay per result. 1 result = 1 job posting.**

| Jobs | Cost at $1.00 / 1,000 |
|---|---|
| 1,000 | $1.00 |
| 25,000 | $25.00 |
| 100,000 | $100.00 |

Compare: LinkedIn job actors run $29.99/month rental *plus* usage — and miss apply URLs.

### Finding boards to scrape

Any company careers page that redirects to `boards.greenhouse.io/...`, `jobs.lever.co/...`, `jobs.ashbyhq.com/...`, `apply.workable.com/...` or `*.recruitee.com` works. Paste the URL as-is.

### Compliance & fair use

These are public, unauthenticated JSON APIs that the providers publish precisely so postings can be syndicated. No login walls, no rate-limit evasion — requests are throttled to one per domain per second and retried politely on transient failures.

**Why no SmartRecruiters or LinkedIn/Indeed.** SmartRecruiters' `robots.txt` disallows every crawler except `LinkedInBot` from the entire site — so we don't scrape it. LinkedIn and Indeed are excluded by design; see the FAQ.

### Using from API / MCP / AI agents

```bash
curl -X POST "https://api.apify.com/v2/acts/<ACTOR_ID>/run-sync-get-dataset-items?token=<TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{ "boardUrls": ["greenhouse:gitlab"], "includeDescription": false }'
```

Works out of the box with the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp) — the input schema is fully described, so AI agents can call it as a tool ("get all open jobs at company X").

### FAQ

**A board returned zero jobs — why?** Check `RUN_SUMMARY` in the run's key-value store: either the company slug is wrong (typo, renamed board) or the board is empty. The error string is recorded per board.

**Can you add Indeed/LinkedIn?** No — by design. This actor only uses stable ATS APIs; that is why it doesn't break.

**Another ATS you need?** Open an issue — adding a provider with a public board API typically ships within a week (as long as its robots.txt allows it).

**What about SmartRecruiters?** Not supported. Its `robots.txt` disallows every crawler except `LinkedInBot`. We won't spoof a user agent to get around that.

### Changelog

- **0.1.0** (2026-07) — Initial release: Greenhouse, Lever, Ashby (incl. compensation), Workable, Recruitee. Unified schema, per-board run summary, per-domain crawl delay.

***

Maintained by **Sturdy Data** — boring, reliable scrapers. Report issues in the Issues tab; we respond within 24 hours.

# Actor input Schema

## `boardUrls` (type: `array`):

Company career board URLs. Supported: boards.greenhouse.io/<company>, job-boards.greenhouse.io/<company>, jobs.lever.co/<company>, jobs.ashbyhq.com/<company>, apply.workable.com/<company>, <company>.recruitee.com. Shorthand also works: greenhouse:stripe, lever:spotify, ashby:openai.

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

When enabled, each posting includes the full description as plain text. Turn off for smaller, faster datasets.

## `maxJobsPerBoard` (type: `integer`):

Safety cap per company board.

## Actor input object example

```json
{
  "boardUrls": [
    "https://boards.greenhouse.io/gitlab",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/openai"
  ],
  "includeDescription": true,
  "maxJobsPerBoard": 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 = {
    "boardUrls": [
        "https://boards.greenhouse.io/gitlab",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/openai"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sturdydata/job-postings-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 = { "boardUrls": [
        "https://boards.greenhouse.io/gitlab",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/openai",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("sturdydata/job-postings-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 '{
  "boardUrls": [
    "https://boards.greenhouse.io/gitlab",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/openai"
  ]
}' |
apify call sturdydata/job-postings-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Job Postings Scraper — Greenhouse, Lever, Ashby, Workable",
        "description": "Scrape live job postings straight from company career boards (Greenhouse, Lever, Ashby, Workable, Recruitee) using their stable public JSON APIs — not fragile HTML. One unified schema across all five ATS providers: title, location, remote flag, department, compensation (where published), apply UR...",
        "version": "0.1",
        "x-build-id": "1bx4mmk9ZNfkYoelh"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/sturdydata~job-postings-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-sturdydata-job-postings-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/sturdydata~job-postings-scraper/runs": {
            "post": {
                "operationId": "runs-sync-sturdydata-job-postings-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/sturdydata~job-postings-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-sturdydata-job-postings-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "boardUrls"
                ],
                "properties": {
                    "boardUrls": {
                        "title": "Career board URLs",
                        "type": "array",
                        "description": "Company career board URLs. Supported: boards.greenhouse.io/<company>, job-boards.greenhouse.io/<company>, jobs.lever.co/<company>, jobs.ashbyhq.com/<company>, apply.workable.com/<company>, <company>.recruitee.com. Shorthand also works: greenhouse:stripe, lever:spotify, ashby:openai.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "includeDescription": {
                        "title": "Include full job description (plain text)",
                        "type": "boolean",
                        "description": "When enabled, each posting includes the full description as plain text. Turn off for smaller, faster datasets.",
                        "default": true
                    },
                    "maxJobsPerBoard": {
                        "title": "Max jobs per board",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Safety cap per company board.",
                        "default": 500
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
