# Career Site Jobs Scraper: Greenhouse, Lever, Ashby and more (`sourcewise/career-site-jobs`) Actor

Get open jobs straight from company career sites: Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable. Paste career page URLs or just company names. Salary, remote/hybrid, full descriptions, and only-new-jobs mode for monitoring.

- **URL**: https://apify.com/sourcewise/career-site-jobs.md
- **Developed by:** [Sourcewise](https://apify.com/sourcewise) (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 $3.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 Site Jobs Scraper: Workday, Greenhouse, Lever, Ashby, Personio, Teamtailor & more

Get **open jobs straight from company career sites**: no job board middlemen, no reposts, no ghost listings. Paste career page URLs or just **company names**, and get clean, structured jobs with salary, remote/hybrid status and full descriptions.

### Why use it?

- 🎯 **Direct from the source.** Data comes from the public job board APIs and career sites of the ATS platforms companies use to hire. That makes it fast and reliable, with no blocked requests. We respect each site's robots.txt.
- 🔎 **Just type a company name.** "Hugging Face", "OpenAI", "Stripe": the Actor finds the company's board across all supported platforms automatically.
- 🔔 **Only new jobs (monitoring mode).** Schedule it daily and get only the jobs that appeared since the last run. You pay only for new jobs.
- 💰 **Salary data** where the company publishes it (Ashby, Lever, Recruitee).
- 🧹 **One normalized schema** across all platforms. The same fields work for every company.
- 🤖 **AI-agent ready.** Simple input and clean JSON output, usable through the Apify MCP server.

### Supported platforms

| Platform | Example career page URL |
|---|---|
| Greenhouse | `https://boards.greenhouse.io/stripe`, `https://job-boards.greenhouse.io/<company>` |
| Lever | `https://jobs.lever.co/spotify` (EU boards supported) |
| Ashby | `https://jobs.ashbyhq.com/openai` |
| SmartRecruiters | `https://jobs.smartrecruiters.com/BoschGroup` |
| Recruitee | `https://<company>.recruitee.com` |
| Workable | `https://apply.workable.com/<company>` |
| Personio | `https://<company>.jobs.personio.de` (official XML job feed) |
| Teamtailor | `https://<company>.teamtailor.com`, or `teamtailor:careers.example.com` for a custom career domain |
| Workday | `https://<company>.wd5.myworkdayjobs.com/<SiteName>` (copy the career site URL from your browser) |

You can also write `ats:slug`, e.g. `greenhouse:stripe` or `workday:nvidia.wd5/NVIDIAExternalCareerSite`.

**Workday notes:** company names can't be auto-detected for Workday, so paste the career site URL. Workday serves at most 2,000 jobs per search. For very large employers, add **title keywords**: they are sent to Workday's own search, so each keyword gets its own 2,000-job window and runs finish faster. Dates are exact when descriptions are included. Without descriptions they're estimated from "Posted 3 Days Ago"-style labels, and `published_at_estimated` is `true`.

### Use cases

- **Job seekers and career coaches:** track target companies and get alerted about new openings.
- **Recruiters and staffing agencies:** watch client and prospect companies for new roles.
- **Job boards and aggregators:** fill niche boards with fresh, first-party postings.
- **Market and talent intelligence:** measure hiring velocity, departments and locations across competitors.
- **Investors:** use hiring as a signal of company growth.

### Input

| Field | Description |
|---|---|
| `companies` | Career page URLs, `ats:slug`, or company names (required) |
| `titleKeywords` | Keep jobs whose title contains any of these words (whole words, case-insensitive) |
| `excludeTitleKeywords` | Drop jobs whose title contains any of these words |
| `locations` | Keep jobs matching any location, city or country (whole words, so `US` won't match `Australia`); `Remote` matches remote jobs |
| `remoteOnly` | Only jobs marked remote |
| `postedWithinDays` | Only jobs published in the last N days |
| `onlyNewJobs` | Return only jobs not seen in previous runs with the same companies list |
| `stateKey` | Optional custom name for the monitoring memory |
| `includeDescription` | Include description HTML and plain text (default: on) |
| `maxJobsPerCompany` / `maxJobs` | Limits (newest jobs first) |

Example:

```json
{
  "companies": ["https://boards.greenhouse.io/stripe", "OpenAI", "lever:spotify"],
  "titleKeywords": ["engineer", "data scientist"],
  "excludeTitleKeywords": ["intern"],
  "locations": ["London", "Remote"],
  "onlyNewJobs": true
}
```

### Output

Each job is one dataset item:

```json
{
  "id": "ashby:openai:240d459b-696d-43eb-8497-fab3e56ecd9b",
  "ats": "ashby",
  "company_slug": "openai",
  "company_name": "OpenAI",
  "job_id": "240d459b-696d-43eb-8497-fab3e56ecd9b",
  "title": "Research Engineer",
  "url": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b",
  "apply_url": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b/application",
  "location": "San Francisco",
  "locations": ["San Francisco"],
  "country": "United States",
  "city": "San Francisco",
  "workplace_type": null,
  "is_remote": null,
  "employment_type": "FullTime",
  "department": "Research",
  "published_at": "2025-04-05T00:03:20Z",
  "published_at_estimated": false,
  "updated_at": null,
  "salary": {"min": 250000, "max": 445000, "currency": "USD", "period": "year", "text": "$250K - $445K"},
  "language": null,
  "description_html": "<p>…</p>",
  "description_text": "…"
}
```

The run's key-value store also contains an `OUTPUT` record with a per-company summary: the detected platform, jobs on the board, jobs matched, jobs returned, and any errors such as a company not found.

### Pricing

You pay per job returned. Filters are applied **before** charging, so you never pay for jobs you filtered out, and in monitoring mode you only pay for new jobs. Set a maximum cost per run in the run options, and the Actor stops cleanly when it reaches it.

### FAQ

**A company name matched the wrong company.** Names can be ambiguous: "Lunar", for example, exists on several platforms. The run summary (`OUTPUT`) lists `other_matches` for each name, and the log shows a warning. Paste the career page URL or `ats:slug` to pick the right one.

**A company isn't found by name.** Its board may use a different slug, or it may be on a platform not yet supported. Paste the career page URL instead. If the company uses another ATS, open an issue and we'll consider adding it.

**Is this legal?** The Actor reads only public job postings that companies publish through their ATS's public job board API, so that job seekers and aggregators can find them. It does not collect personal data.

**How fresh is the data?** Live. Every run fetches the boards directly.

# Actor input Schema

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

Career page URLs (e.g. https://boards.greenhouse.io/stripe, https://jobs.lever.co/spotify, https://jobs.ashbyhq.com/openai, https://tado.jobs.personio.de, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite), 'ats:slug' (e.g. greenhouse:stripe, teamtailor:careers.example.com), or plain company names (e.g. Hugging Face), which are auto-detected across Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee, Workable, Personio and Teamtailor. Workday needs the career site URL.

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

Keep jobs whose title contains any of these words (case-insensitive, whole words). Leave empty for all jobs. For Workday they are also sent to Workday's search, which speeds up runs on large career sites.

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

Drop jobs whose title contains any of these words, e.g. 'Senior', 'Intern'.

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

Keep jobs whose location, city or country contains any of these as whole words (e.g. 'Berlin', 'United States', 'US', 'GB'). 'Remote' matches remote jobs.

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

Keep only jobs the company marks as remote.

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

Keep only jobs published in the last N days. Jobs without a date are kept.

## `onlyNewJobs` (type: `boolean`):

Return only jobs not returned by a previous run with the same companies list. Ideal for scheduled runs and alerts: you only pay for new jobs.

## `stateKey` (type: `string`):

Optional name for the 'seen jobs' memory used by Only new jobs. By default it is derived from the companies list. Use a custom key to share state across tasks or to reset it.

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

Include full description as HTML and plain text.

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

0 = no limit. Newest jobs first.

## `maxJobs` (type: `integer`):

0 = no limit. Also capped by the maximum cost per run you set.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/stripe",
    "https://jobs.ashbyhq.com/openai",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "Hugging Face"
  ],
  "remoteOnly": false,
  "onlyNewJobs": false,
  "includeDescription": true,
  "maxJobsPerCompany": 0,
  "maxJobs": 0
}
```

# Actor output Schema

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

Normalized job postings (one item per job) in the default dataset.

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

Per-company summary: detected ATS, jobs on board, matched, returned, and errors.

# 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": [
        "https://boards.greenhouse.io/stripe",
        "https://jobs.ashbyhq.com/openai",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "Hugging Face"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sourcewise/career-site-jobs").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": [
        "https://boards.greenhouse.io/stripe",
        "https://jobs.ashbyhq.com/openai",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "Hugging Face",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("sourcewise/career-site-jobs").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": [
    "https://boards.greenhouse.io/stripe",
    "https://jobs.ashbyhq.com/openai",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "Hugging Face"
  ]
}' |
apify call sourcewise/career-site-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sourcewise/career-site-jobs"
        }
    }
}
```

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/nt1PsnOb0rgjHIDFR/builds/2lCOryggSch61qmhZ/openapi.json
