# Career Page Jobs Scraper: Greenhouse, Lever, Ashby, Workable (`nikaido_thc/company-jobs-scraper`) Actor

ATS jobs API for company career pages. Give company names or domains, get every open job from Greenhouse, Lever, Ashby, Workable, Recruitee and SmartRecruiters in one format, with salary ranges and full descriptions. Filter by title, location, remote and date.

- **URL**: https://apify.com/nikaido_thc/company-jobs-scraper.md
- **Developed by:** [Ogochukwu Ozor](https://apify.com/nikaido_thc) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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.

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

## Career Page Jobs Scraper: Greenhouse, Lever, Ashby, Workable

An **ATS jobs API** for company career pages. Get **every open job from the companies you name**, in one clean format, straight from their official job boards.

Type a company name, website or job board link. The scraper works out which hiring system (ATS) the company uses, reads its public job board and returns every listing with title, location, remote/hybrid, department, employment type, posting date, apply link, **salary where published** and the full description.

- **6 hiring systems:** Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters
- **No ATS detective work:** give "Stripe", "stripe.com" or a board URL; it finds the board
- **One schema for all:** the same fields whatever system the company uses
- **Salary ranges:** from Ashby, Lever and Recruitee listings, Greenhouse pay-transparency ranges, and ranges written in descriptions
- **Fresh:** read live from the company's board on every run, nothing cached
- **Official endpoints only:** each system's public job board API, the same one that powers the company's careers page. No logins, no proxies.

### Supported hiring systems (ATS)

| ATS | Example board URL you can paste | Salary data |
|---|---|---|
| Greenhouse | `https://job-boards.greenhouse.io/airbnb` or `boards.greenhouse.io/airbnb` | Pay-transparency ranges (mostly US jobs) |
| Lever | `https://jobs.lever.co/palantir` (EU boards too) | Salary range when the company sets one |
| Ashby | `https://jobs.ashbyhq.com/openai` | Compensation ranges, often with equity |
| Workable | `https://apply.workable.com/huggingface/` | Ranges written in the description |
| Recruitee | `https://bunq.recruitee.com` | Salary field when published |
| SmartRecruiters | `https://jobs.smartrecruiters.com/BoschGroup` | Ranges written in the description |

Or just type the company name or website and let the scraper find the board.

### Who it's for

- **Job seekers and job boards:** track openings at target companies, build niche job boards and job alerts
- **Sales and lead generation:** use hiring signals (who is hiring, for which teams, where) to find companies that need your product
- **Recruiters and talent teams:** watch competitors' open roles and new team build-outs
- **Investors and analysts:** follow headcount growth, new offices and salary ranges across a portfolio
- **AI agents and automations:** structured job postings data from named companies, ready for LLMs

### How to use it

1. Click **Try for free**.
2. Add companies, one per line: `Stripe`, `notion.so`, `https://jobs.lever.co/palantir`.
3. Optionally filter by title, location, department, remote or posting date.
4. Click **Start**. Results come back as a table you can export to JSON, CSV, Excel or HTML.

A board URL is the most reliable input. A plain name works when the company's board uses its name (most do). If a name isn't found, the run summary tells you, and pasting the careers page URL usually fixes it.

### Input

| Field | Default | What it does |
|---|---|---|
| Companies | — | Names, websites or job board URLs |
| Job title contains | all | Keep titles containing any of these words |
| Job title does not contain | — | Drop titles containing any of these, e.g. intern |
| Location contains | all | e.g. London, Germany, Remote |
| Department or team contains | all | e.g. Engineering, Sales |
| Remote jobs only | off | Only jobs marked remote |
| Posted within the last N days | any | e.g. 7 for last week's jobs |
| Include job descriptions | on | Full description as plain text |
| Fetch Greenhouse pay ranges | on | One extra quick request per Greenhouse job |
| Maximum jobs per company | no limit | Newest first |
| Maximum jobs in total | 1000 | You pay per job saved |

### Output example

```json
{
  "company": "Airbnb",
  "ats": "greenhouse",
  "boardSlug": "airbnb",
  "jobId": "7712345",
  "title": "Senior Software Engineer, Payments",
  "department": "Engineering",
  "location": "United States",
  "remote": true,
  "workplaceType": "Remote",
  "employmentType": null,
  "postedAt": "2026-11-03T10:12:00-04:00",
  "url": "https://careers.airbnb.com/positions/7712345?gh_jid=7712345",
  "applyUrl": "https://careers.airbnb.com/positions/7712345?gh_jid=7712345",
  "salaryMin": 212000,
  "salaryMax": 265000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "salaryText": "Pay Range: 212,000-265,000 USD",
  "salarySource": "job board",
  "descriptionText": "Airbnb was born in 2007 when ...",
  "input": "Airbnb",
  "scrapedAt": "2026-11-06T09:00:00+00:00"
}
```

Values are standardised across systems: `workplaceType` is Remote, Hybrid or On-site; `employmentType` is Full-time, Part-time, Contract, Internship or Temporary; `salaryPeriod` is hour, day, week, month or year. Fields a company doesn't publish are `null`.

A **SUMMARY** record in the run's key-value store lists, for each input, the job board found, how it was found and how many jobs are open, plus any other boards that matched the same name.

### Pricing

**$2 per 1,000 jobs saved.** A 50-company run with 2,000 jobs costs about $4. Filters are applied before saving, so you only pay for the jobs you keep. You can cap the maximum charge per run.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/nikaido_thc~company-jobs-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["Stripe", "OpenAI"], "titleKeywords": ["engineer"], "postedWithinDays": 7}'
```

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("nikaido_thc/company-jobs-scraper").call(
    run_input={"companies": ["Stripe", "OpenAI"], "remoteOnly": True}
)
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["company"], job["title"], job["location"], job["salaryText"])
```

Schedule it daily with Apify **Schedules** and send new jobs to Google Sheets, Slack, a webhook, Make, Zapier or n8n through **Integrations**. AI agents can call it through the Apify MCP server.

### FAQ

**How is this different from LinkedIn or Indeed job scrapers?**
Jobs come straight from the company's own careers page, so they are the original postings with the direct apply link, appear there first, and include the full description and published salary. No job board duplicates or reposted agency ads.

**Which companies are supported?**
Any company whose careers page runs on Greenhouse, Lever, Ashby, Workable, Recruitee or SmartRecruiters. That includes a large share of tech companies and startups. Workday, iCIMS, Taleo and in-house career sites are not supported yet.

**Why wasn't my company found?**
Its board may use a different name from the company (e.g. "acme-corp"), or it uses a system not listed above. Paste the careers page or job board URL instead.

**Why is salary missing for some jobs?**
Only some companies publish pay. US jobs on Greenhouse often have pay-transparency ranges; many European jobs don't publish salary at all.

**Is this allowed?**
The scraper only reads the public job board endpoints that each hiring system provides so companies can show their jobs on their own careers sites. It collects job listings only, no applicant or candidate data.

### Feedback

Want another hiring system or field? Open an issue on the **Issues** tab.

# Actor input Schema

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

Company names (Stripe), websites (stripe.com) or job board URLs (https://jobs.lever.co/palantir). Names are matched to a job board automatically; a URL is the most reliable.

## `titleKeywords` (type: `array`):

Keep jobs whose title contains any of these words (case-insensitive). Empty = all jobs.

## `excludeTitleKeywords` (type: `array`):

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

## `locationKeywords` (type: `array`):

Keep jobs whose location, city, region or country contains any of these, e.g. London, Germany, Remote.

## `departmentKeywords` (type: `array`):

Keep jobs whose department or team contains any of these, e.g. Engineering, Sales.

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

Keep only jobs the company marks as remote, or whose location says Remote.

## `postedWithinDays` (type: `integer`):

Keep only jobs posted in the last N days. 0 = any date. Jobs without a posting date are kept.

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

Add the full job description as plain text. Turn off for faster runs and smaller results.

## `greenhouseSalaries` (type: `boolean`):

Greenhouse lists pay ranges (required by US pay-transparency laws) on each job's own page. This adds one quick request per Greenhouse job. Other systems include salary in the main listing.

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

Newest first. 0 = no limit.

## `maxResults` (type: `integer`):

You are charged per job saved.

## Actor input object example

```json
{
  "companies": [
    "Stripe",
    "OpenAI",
    "palantir",
    "https://apply.workable.com/huggingface/"
  ],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": true,
  "greenhouseSalaries": true,
  "maxJobsPerCompany": 0,
  "maxResults": 1000
}
```

# Actor output Schema

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

Table of open jobs in one format across all hiring systems.

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

Which job board was found for each company, how, and how many jobs it has open.

# 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",
        "OpenAI",
        "palantir",
        "https://apply.workable.com/huggingface/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nikaido_thc/company-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": [
        "Stripe",
        "OpenAI",
        "palantir",
        "https://apply.workable.com/huggingface/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("nikaido_thc/company-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": [
    "Stripe",
    "OpenAI",
    "palantir",
    "https://apply.workable.com/huggingface/"
  ]
}' |
apify call nikaido_thc/company-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nikaido_thc/company-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/MvE2LecgiGk8fiYDA/builds/dhqfB800zKm2eV9Le/openapi.json
