# Greenhouse, Lever, Ashby & SmartRecruiters Jobs Scraper (`firsthand-data/career-page-jobs-scraper`) Actor

Get every open job from company career pages on Greenhouse, Lever, Ashby and SmartRecruiters in one clean table: title, team, city, country, remote, salary as numbers, dates, links and description. Only-new mode returns new and closed jobs since your last run. No login, no proxy.

- **URL**: https://apify.com/firsthand-data/career-page-jobs-scraper.md
- **Developed by:** [Firsthand Data](https://apify.com/firsthand-data) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Greenhouse, Lever, Ashby & SmartRecruiters Jobs Scraper

Get every open job straight from company career pages on **Greenhouse, Lever, Ashby and
SmartRecruiters** in one clean table. Give it job boards (`greenhouse:stripe`), job board links or
just company websites, or pick a ready-made list of companies, and get titles, teams, cities,
countries, remote flags, salaries as numbers, dates, links and full descriptions.

Turn on **Only new and closed** and put it on a schedule: every run returns only the jobs that
appeared or disappeared since the previous run. You pay only for new jobs.

- ✅ Official public job board APIs: no login, no API key, no proxies, no browser
- ✅ Four applicant tracking systems (ATS) in one output format
- ✅ Finds the job board from a company website
- ✅ Salary parsed into minimum, maximum and currency
- ✅ New and closed jobs between runs; closed rows are free
- ✅ No personal data: recruiter fields are dropped, emails and phone numbers are removed from descriptions
- 💲 **$2 per 1,000 jobs.** The Apify free plan ($5 of credit every month) covers about 2,500 jobs.

### What can you do with this career page scraper?

- **Sales and RevOps: hiring signals.** A company that opens ten sales roles is growing and
  buying. Watch your target accounts and get their new roles every morning.
- **Recruiters and agencies.** Track openings at the companies you work with, straight from
  their own career pages.
- **Job boards and newsletters.** Build a job feed from a list of employers. Only-new mode adds
  new jobs and tells you which ones closed, so you can expire them.
- **Market and salary research.** Compare roles, locations and published pay ranges across companies.
- **AI agents.** Let Claude, Cursor or any MCP client answer "is Linear hiring engineers in
  Europe?" with live data.

### How to scrape jobs from Greenhouse, Lever, Ashby and SmartRecruiters

1. Click **Try for free**. The Apify free plan needs no credit card.
2. In **Companies**, add one company per line: `greenhouse:stripe`, a job board link such as
   `https://jobs.lever.co/spotify`, or a website such as `stripe.com`.
3. Optionally add filters: words in the job title, locations, remote only.
4. Click **Start**. Download the results as JSON, CSV or Excel, or read them through the Apify API.

The form comes prefilled with Discord (Greenhouse), Spotify (Lever), Linear (Ashby) and Canva
(SmartRecruiters). On October 18, 2026 this run took 20 seconds and returned 269 jobs, about $0.54.

### Get only new jobs every morning

1. Set **What to return** to **Only new and closed since the last run** and give the watch a
   name, for example `target-accounts`.
2. Run it once. The first run returns all open jobs as new: this is your starting point.
3. Click **Save as new task**, open **Schedules** and run the task every day (or every hour).
4. In the task's **Integrations** tab, send the results to Slack, email, Zapier, Make or n8n
   (and from there to Google Sheets, Airtable or your CRM), or to your own webhook.

Every later run returns only jobs that are new (`changeStatus: "new"`) and jobs that disappeared
from the board (`changeStatus: "closed"`). Closed rows are free, and a quiet day costs nothing.
Use a separate watch name for each list of companies.

### Ready-made company lists

No list of companies yet? Pick one in **Ready-made company lists**. A list contains only companies
whose job boards had open jobs when we checked them, and we refresh the lists every month. You can
combine a list with your own companies and with all filters.

| List | Who is in it | Companies | Open jobs on Oct 18, 2026 |
|---|---|---|---|
| Remote-first companies | at least half of the open jobs are remote; 5 to 1,000 open jobs | 1,040 | 27,502 |

A whole list returns many jobs: running the remote-first list once without filters returns about
27,500 jobs (about $55). To pay less, add title words, **Remote jobs only** or locations, use
only-new mode, or set **Maximum cost per run**. Example: on October 18, 2026 the remote-first list
with title "engineer" and **Remote jobs only** returned 5,630 jobs from 748 companies (about $11).
Switch that to only-new mode and schedule it daily: you get a feed of new remote engineering jobs.

### What data can you extract from career pages?

| Field | Example | Notes |
|---|---|---|
| `company` | Discord | name from the job board |
| `title` | Commercial Policy Lead | |
| `department`, `team` | Policy | where the board gives it |
| `location`, `city`, `region`, `country` | San Francisco Bay Area | parsed from the board; `allLocations` keeps every location of the job |
| `workplaceType` | remote, hybrid, onsite, unknown | |
| `employmentType` | full_time | where the board gives it |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | 192000, 216000, USD | from salary fields or the description text |
| `salaryText` | The US base salary range for this full-time position is $192,000 to $216,000... | original salary text |
| `publishedAt`, `updatedAt` | 2026-09-15T16:52:11.000Z | |
| `url`, `applyUrl` | https://job-boards.greenhouse.io/discord/jobs/8806482002 | |
| `description` | plain text | emails and phone numbers removed |
| `id`, `source`, `board`, `sourceJobId` | greenhouse:discord:8806482002 | stable id for de-duplication |
| `changeStatus` | new, closed or empty | only in only-new mode |
| `scrapedAt` | 2026-10-18T10:02:51.092Z | time of the run |

Six rows from the prefilled run on October 18, 2026:

| Company | Title | Location | Workplace | Salary | Published |
|---|---|---|---|---|---|
| Discord | Commercial Policy Lead | San Francisco Bay Area | | 192,000-216,000 USD | 2026-09-15 |
| Discord | Data Scientist - Client Platform | San Francisco Bay Area | | 160,000-200,000 USD | 2026-09-24 |
| Canva | Senior Legal Counsel, Intellectual Property (Tech Transactions) | San Francisco, United States | hybrid | 190,000-280,000 USD | 2026-10-16 |
| Canva | Localisation Lead, Indonesia (Bahasa Indonesia Speaker Required) | Singapore | remote | | 2026-10-16 |
| Spotify | Art Director - Mexico | Mexico City, Mexico | hybrid | | 2026-10-09 |
| Linear | Senior / Staff Fullstack Engineer | European Union | remote | | 2021-04-27 |

In that run 57 of 269 jobs had a salary range and 80 were remote. Empty cells are values the
job board does not publish.

One job as JSON (description shortened):

```json
{
  "id": "greenhouse:discord:8806482002",
  "source": "greenhouse",
  "board": "discord",
  "sourceJobId": "8806482002",
  "company": "Discord",
  "title": "Commercial Policy Lead",
  "department": "Policy",
  "team": null,
  "location": "San Francisco Bay Area",
  "city": "San Francisco Bay Area",
  "region": null,
  "country": null,
  "workplaceType": "unknown",
  "allLocations": ["San Francisco Bay Area"],
  "employmentType": null,
  "salaryMin": 192000,
  "salaryMax": 216000,
  "salaryCurrency": "USD",
  "salaryPeriod": null,
  "salaryText": "The US base salary range for this full-time position is $192,000 to $216,000 + equity + benefits.",
  "publishedAt": "2026-09-15T16:52:11.000Z",
  "updatedAt": "2026-10-15T20:08:17.000Z",
  "url": "https://job-boards.greenhouse.io/discord/jobs/8806482002",
  "applyUrl": null,
  "description": "Discord has a highly engaged community of millions of daily active users...",
  "changeStatus": null,
  "scrapedAt": "2026-10-18T10:02:51.092Z"
}
```

### How much does it cost to scrape career pages?

- **$2 per 1,000 jobs** (pay per event). Apify platform usage is included in the price.
- **Free:** closed-job rows, companies without open jobs, companies that are not found, errors.
- In only-new mode the first run returns all open jobs (your starting point); later runs return
  only new ones.
- The Apify free plan gives $5 of credit every month: about 2,500 jobs.
- Set **Maximum cost per run** in the run options: the scraper stops before it goes over your limit.

| What you run | Jobs | Cost |
|---|---|---|
| The prefilled input (4 companies) | 269 | about $0.54 |
| 50 companies, all open jobs, once (about 100 jobs each) | about 5,000 | about $10 |
| The same 50 companies every day in only-new mode, if they post 40 new jobs a day | about 1,200 a month | about $2.40 a month |

### Input

#### Three ways to add a company

| You write | Example | What happens |
|---|---|---|
| `system:board` | `greenhouse:stripe`, `lever:spotify`, `ashby:linear`, `smartrecruiters:Canva` | read directly |
| Job board link | `https://boards.greenhouse.io/stripe`, `https://jobs.lever.co/spotify`, `https://jobs.ashbyhq.com/linear`, `https://jobs.smartrecruiters.com/Canva` | read directly |
| Company website | `stripe.com` | the scraper looks for a job board link on the website (home page, `/careers`, `/jobs`). If there is none, it tries the domain name as a board name and says so in the run summary |

**How to find a board name:** open any job on the company's careers page. The link shows the
system and the board, for example `jobs.ashbyhq.com/linear/...` means `ashby:linear`.

The same company written twice (in any letter case or as different links) is read and charged once.

#### Example input

```json
{
  "companies": ["greenhouse:discord", "https://jobs.lever.co/spotify", "stripe.com", "smartrecruiters:Canva"],
  "mode": "changes",
  "watchName": "target-accounts",
  "includeKeywords": ["engineer", "data"],
  "excludeKeywords": ["intern"],
  "locations": ["Germany", "United Kingdom"],
  "remoteOnly": false,
  "includeDescription": true
}
```

#### Run summary

Each run saves a summary to the key-value store record `OUTPUT`: for every company the system,
board, status (`ok`, `not_found` or `error`), the number of jobs and a note when something needs
your attention. A company that fails never stops the run.

### Which job boards are supported?

| System | Board link | Example | Notes |
|---|---|---|---|
| Greenhouse | `boards.greenhouse.io/{board}`, `job-boards.greenhouse.io/{board}` | `stripe` | salary is often found in the description text |
| Lever | `jobs.lever.co/{board}` | `spotify` | salary range where the company publishes it |
| Ashby | `jobs.ashbyhq.com/{board}` | `linear` | unlisted jobs are skipped |
| SmartRecruiters | `jobs.smartrecruiters.com/{board}` | `Canva` | public jobs only; each description is a separate request, so big companies take longer |

Job boards hosted in the EU (`eu.greenhouse.io`, `jobs.eu.lever.co`) are not supported yet.

### Use it with AI agents (MCP)

This scraper works as a tool for AI agents through the Apify MCP server: Claude, Cursor, VS Code,
n8n and other MCP clients. Add this URL as a remote MCP server and sign in to Apify when your
browser opens:

```
https://mcp.apify.com?tools=firsthand-data/career-page-jobs-scraper
```

Then ask, for example, "list open engineering jobs at Linear and Discord". Turn off **Include job
description** to keep answers short.

### Integrations

- **Slack and email:** the **Integrations** tab of a run or a saved task.
- **Zapier, Make, n8n:** start on "Run succeeded" and read the dataset; from there send jobs to
  Google Sheets, Airtable, HubSpot or any other app.
- **Webhooks:** your endpoint gets a call when a run finishes.
- **Clay:** an HTTP request to the Apify `run-sync-get-dataset-items` endpoint with your
  companies as input returns the rows straight into your table (a synchronous run must finish
  within 300 seconds).
- **API:** JavaScript, Python and CLI examples are on the **API** tab of this page.

### Fair use and data quality

- Reads only the official public job board APIs that these systems provide for career pages.
- Keeps to each source's rules: SmartRecruiters at most about 9 requests per second (their limit
  is 10), Lever job pages at most one request per second (their robots.txt), company websites
  only where robots.txt allows.
- Reads only the companies you list. No logins, no proxies, no hidden or unlisted jobs.
- No personal data: recruiter names and photos are not collected; emails and phone numbers are
  removed from descriptions.
- Results and the only-new memory stay in your own Apify account. We do not keep copies.
- Not affiliated with Greenhouse, Lever, Ashby or SmartRecruiters. Their names are trademarks of
  their owners.

### FAQ

**Do I need an API key or a proxy?**
No. All four systems publish open jobs through public job board endpoints.

**Why is a company "not found"?**
The board name is wrong, or the company moved to another system. Check a job link on its careers
page. SmartRecruiters returns the same empty list for an unknown company and for a company with
no open jobs; the run summary says so.

**Why are big SmartRecruiters companies slower?**
Each description is a separate request, and the scraper keeps to SmartRecruiters' rate limit. A
company with thousands of jobs can take several minutes. Turn off **Include job description** to
finish in seconds.

**What counts as a new job?**
A job that the watch has not returned before. Board names are not case-sensitive, so the same
job is never returned as new twice, even if you write `Acme` one day and `acme` the next.

**Can I get jobs from Workday, iCIMS, LinkedIn or Indeed?**
Not in this Actor. It reads only systems with an official public job board API. More systems
are added after we check their terms.

**How fresh is the data?**
Live: the scraper reads each job board at the moment you run it.

### Changelog and support

- **0.1 (October 2026):** first public version: Greenhouse, Lever, Ashby and SmartRecruiters,
  only-new mode, job board detection from company websites.
- We add output fields; we do not rename or remove them. Price changes are announced in advance.
- Questions, bugs or a job board you need: open an issue on the **Issues** tab. We usually answer
  within 1-3 days.
- If this scraper saved you time, a short review helps other people find it. Thank you!

# Actor input Schema

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

One company per line: "system:board" (greenhouse:stripe, lever:spotify, ashby:linear, smartrecruiters:Canva), a job board link (https://jobs.lever.co/spotify) or the company website (stripe.com) - the scraper finds its job board itself. Tip: open any job on the company's careers page - the link shows the system and the board name.

## `companyLists` (type: `array`):

Add whole lists of companies with live job boards, checked by us and refreshed monthly. They are added to the companies above. A list returns many jobs: add filters, use "Only new and closed" or set the maximum cost per run to control the price. Sizes are in the README.

## `mode` (type: `string`):

All open jobs every run, or only jobs that are new or closed since the previous run with the same watch name (you pay only for new jobs; closed rows are free).

## `watchName` (type: `string`):

Used only with "Only new and closed": the robot remembers what it already returned under this name. Use a different name for each company list.

## `includeKeywords` (type: `array`):

Keep only jobs whose title contains at least one of these words. Case-insensitive. Empty - keep all.

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

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

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

Keep only jobs whose city, region, country or location text contains one of these, e.g. "Germany", "London".

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

Keep only jobs marked as remote.

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

Plain-text description without emails and phone numbers. Turn off for faster runs on very large SmartRecruiters companies (there each description is a separate request).

## Actor input object example

```json
{
  "companies": [
    "greenhouse:discord",
    "lever:spotify",
    "ashby:linear",
    "smartrecruiters:Canva"
  ],
  "mode": "all",
  "watchName": "default",
  "remoteOnly": false,
  "includeDescription": true
}
```

# Actor output Schema

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

Every job returned by this run: company, title, department, location, remote flag, salary, dates, links, description and change status (new or closed in only-new mode).

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

For every company: job board system, board name, status (ok, not_found or error), number of jobs and a note when something needs attention.

# 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": [
        "greenhouse:discord",
        "lever:spotify",
        "ashby:linear",
        "smartrecruiters:Canva"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("firsthand-data/career-page-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": [
        "greenhouse:discord",
        "lever:spotify",
        "ashby:linear",
        "smartrecruiters:Canva",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("firsthand-data/career-page-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": [
    "greenhouse:discord",
    "lever:spotify",
    "ashby:linear",
    "smartrecruiters:Canva"
  ]
}' |
apify call firsthand-data/career-page-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,firsthand-data/career-page-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/KQwGziyQ5h76BXwp6/builds/Dfsig7yY5FuAERvFU/openapi.json
