# Career Page Jobs Scraper (Greenhouse, Lever, Ashby, Workday) (`octopull/career-page-jobs-scraper`) Actor

Open jobs straight from company career pages: Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, Recruitee and Personio. Salary where published, remote flag, full description, and a new-jobs-only mode for scheduled runs. No login.

- **URL**: https://apify.com/octopull/career-page-jobs-scraper.md
- **Developed by:** [Yogi Wahyu Prasida](https://apify.com/octopull) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.56 / 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

## Career Page Jobs Scraper (Greenhouse, Lever, Ashby, Workday)

Get open jobs **straight from company career pages**, the source job boards copy from. One
Actor covers the applicant tracking systems most companies use: **Greenhouse, Lever, Ashby,
Workday, Workable, SmartRecruiters, Recruitee and Personio**. Every job comes back in one clean format:
title, department, locations, remote/hybrid, employment type, salary where the company
publishes it, posting date, apply link and the full description.

No login, no API keys, no proxies. It reads the same public job-board feeds that power the
companies' own careers pages, so results are complete and current.

**Built for:** sales and GTM teams tracking hiring signals, niche job boards and aggregators,
recruiters watching competitors, and AI agents that need fresh job data.

| company | title | location | workplaceType | salary | postedAt |
|---|---|---|---|---|---|
| OpenAI | Research Engineer | San Francisco | hybrid | $250K–$445K / year | 2025-04-05 |
| Anthropic | 3P Revenue Accounting & Reporting | San Francisco, CA; Seattle, WA | — | $190K–$230K / year | 2026-10-28 |
| Spotify | Account Executive - Commercial | New York, NY | onsite | — | 2026-10-09 |

### What you can use it for

- **Job aggregators and niche job boards:** pull fresh jobs from hundreds of target companies
  every day.
- **Recruiters and talent teams:** watch competitors' hiring and get new roles as they open.
- **Sales and investors (hiring signals):** a company opening 10 data-engineering roles is buying
  data tools. Track hiring by department and location.
- **Job seekers:** one list of every remote engineering role at your 50 dream companies.
- **Alerts:** schedule it daily with **Only new jobs** on and send new roles to Slack, email,
  Google Sheets or a webhook through Apify integrations.

### Input

Add companies in any of these forms, mixed freely:

| You enter | Example | What happens |
|---|---|---|
| A job board URL | `https://jobs.lever.co/spotify`, `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite` | Used directly |
| A company website or careers page | `https://www.notion.com/careers`, `linear.app` | The Actor finds the job board linked from it |
| `ats:slug` | `greenhouse:stripe`, `ashby:openai` | Used directly |
| A company name | `OpenAI`, `Hugging Face` | Looked up on Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters and Personio; a board with open jobs wins over an empty old one |

Workday boards can't be guessed from a name: paste the careers page or the `myworkdayjobs.com` URL.

| Field | What it does |
|---|---|
| `titleKeywords` / `excludeTitleKeywords` | Keep titles containing any of these / drop titles containing any of these (case-insensitive). |
| `locationKeywords` | Keep jobs whose location or country contains one of these (`London`, `Germany`, `Remote`). |
| `remoteOnly` | Only remote jobs. |
| `postedAfter` | `2026-10-01`, `7 days`, `24 hours`. Jobs without a published date are kept. |
| `maxJobsPerCompany` | Cap per company after filters (default 1,000). |
| `includeDescription` | Plain-text description (default on). Off = faster Workday and SmartRecruiters runs. |
| `includeDescriptionHtml` | Also return the original HTML. |
| `onlyNewJobs` + `monitorKey` | Return only jobs not seen in earlier runs under the same monitor name. |

### Output

One dataset item per job:

```json
{
  "company": "OpenAI",
  "ats": "ashby",
  "boardUrl": "https://jobs.ashbyhq.com/openai",
  "jobId": "240d459b-696d-43eb-8497-fab3e56ecd9b",
  "title": "Research Engineer",
  "department": "Research",
  "team": "Research",
  "location": "San Francisco",
  "locations": ["San Francisco"],
  "country": "United States",
  "workplaceType": "hybrid",
  "isRemote": false,
  "employmentType": "Full Time",
  "seniority": null,
  "salary": {"min": 250000, "max": 445000, "currency": "USD", "interval": "year", "text": "$250K - $445K"},
  "url": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b",
  "applyUrl": "https://jobs.ashbyhq.com/openai/240d459b-696d-43eb-8497-fab3e56ecd9b/application",
  "postedAt": "2025-04-05T00:03:20+00:00",
  "updatedAt": null,
  "descriptionText": "By applying to this role, you will be considered for ...",
  "scrapedAt": "2026-10-30T08:12:41+00:00"
}
```

A **COMPANIES** record in the run's key-value store lists every input with the board it resolved
to, the number of jobs, and a reason for anything not found, so you can fix a list quickly.

What each ATS publishes differs. Salary comes from Greenhouse, Ashby, Lever and Recruitee wherever
the company publishes a pay range (common for US roles under pay-transparency laws); Workday,
Workable, SmartRecruiters and Personio don't expose pay in their feeds.
Workday shows posting dates as "Posted 3 Days Ago", which become day-precision dates.

### Use it in Clay, n8n, Make or Zapier

- **Clay:** add the enrichment **Run Apify Actor**, pick `octopull/career-page-jobs-scraper`, and map a
  column of company websites or names to `companies`. Or create a table with **Import data from Apify
  actor** and point it at a scheduled task, so new runs keep the table current.
- **n8n / Make / Zapier:** use the Apify node or app, action **Run Actor** (or **Run task**), then read
  the dataset items. A daily schedule with **Only new jobs** gives you a clean "new roles at my target
  accounts" trigger for Slack, HubSpot or email.

### Use it from AI agents (MCP)

AI assistants and agents can call this Actor through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp).
To give an agent just this tool, connect it to:

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

Then ask, for example: *"List remote data-engineering jobs at Stripe, Notion and Datadog posted this week."*
The agent fills `companies`, `titleKeywords`, `remoteOnly` and `postedAfter` from the request.

### Monitoring new jobs

Turn on **Only new jobs** and schedule the Actor (daily is typical). It remembers the jobs it
returned under your **Monitor name** and from then on returns, and charges for, only jobs it
hasn't seen. The first run returns everything, which becomes the baseline. Use one monitor name
per schedule or company list.

### Pricing

Pay per result: you are charged once per job in the dataset, with lower prices on Apify's
Bronze, Silver and Gold plans. With **Only new jobs**, jobs already seen cost nothing. Set a **maximum cost per run** in the run options and the Actor stops
cleanly at it, keeping everything collected so far.

Worked example: 40 companies with about 50 matching jobs each = 2,000 jobs = 2,000 result events.

### Limits and good to know

- Public job postings only. Internal or login-only postings are not visible.
- Workday, SmartRecruiters and Personio need one extra request per job for the description, so big boards
  take a few minutes. Filters are applied before those requests, so filtering also saves time.
- If a company moves to another ATS, its old board URL returns "not found" in the COMPANIES record;
  enter its website instead and the Actor finds the new board.
- If every company you entered is not found, the run fails with a message, so a scheduled run
  won't silently return nothing.

### Is it legal?

The Actor reads job postings that companies publish openly through their ATS's public job-board
feeds, the same data anyone sees on their careers page. It does not log in or collect candidate
data. You are responsible for using the data in line with the companies' terms and the laws that
apply to you; republishing full job descriptions may need the employer's permission.

# Actor input Schema

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

One per line. Any of: a job board URL (<code>https://jobs.lever.co/spotify</code>, <code>https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite</code>), a company website or careers page (<code>https://www.notion.com/careers</code>, the board is found from its links), <code>ats:slug</code> (<code>greenhouse:stripe</code>), or a plain company name (<code>OpenAI</code>, looked up on Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters and Personio). Workday boards need a URL.

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

Keep jobs whose title contains at least one of these (case-insensitive). Empty = all jobs.

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

Drop jobs whose title contains any of these, e.g. <code>intern</code>, <code>senior</code>.

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

Keep jobs whose location or country contains one of these, e.g. <code>London</code>, <code>Germany</code>, <code>Remote</code>.

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

Keep only jobs the company marks as remote (or whose location says remote).

## `postedAfter` (type: `string`):

A date (<code>2026-10-01</code>), a timestamp, or relative (<code>7 days</code>, <code>24 hours</code>). Jobs with no published date are kept.

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

Cap per company, after filters.

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

Full description as plain text. Turn off for faster runs on Workday, SmartRecruiters and Personio, which need one extra request per job.

## `includeDescriptionHtml` (type: `boolean`):

Adds the original HTML next to the plain text.

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

Remembers jobs from earlier runs with the same monitor name and returns only jobs not seen before. You pay only for new jobs. The first run returns everything.

## `monitorKey` (type: `string`):

Use a different name per schedule or per list of companies so their memories stay separate.

## Actor input object example

```json
{
  "companies": [
    "https://job-boards.greenhouse.io/stripe",
    "https://jobs.lever.co/spotify",
    "OpenAI",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "titleKeywords": [],
  "excludeTitleKeywords": [],
  "locationKeywords": [],
  "remoteOnly": false,
  "maxJobsPerCompany": 20,
  "includeDescription": true,
  "includeDescriptionHtml": false,
  "onlyNewJobs": false,
  "monitorKey": "default"
}
```

# Actor output Schema

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

No description

# 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://job-boards.greenhouse.io/stripe",
        "https://jobs.lever.co/spotify",
        "OpenAI",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ],
    "titleKeywords": [],
    "excludeTitleKeywords": [],
    "locationKeywords": [],
    "postedAfter": "",
    "maxJobsPerCompany": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("octopull/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": [
        "https://job-boards.greenhouse.io/stripe",
        "https://jobs.lever.co/spotify",
        "OpenAI",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    ],
    "titleKeywords": [],
    "excludeTitleKeywords": [],
    "locationKeywords": [],
    "postedAfter": "",
    "maxJobsPerCompany": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("octopull/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": [
    "https://job-boards.greenhouse.io/stripe",
    "https://jobs.lever.co/spotify",
    "OpenAI",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "titleKeywords": [],
  "excludeTitleKeywords": [],
  "locationKeywords": [],
  "postedAfter": "",
  "maxJobsPerCompany": 20
}' |
apify call octopull/career-page-jobs-scraper --silent --output-dataset

```

## MCP server setup

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