# Careers Page Scraper | $2/1K | Domain to Open Jobs (`om_kh/careers-page-scraper`) Actor

Paste company websites, get every open job from their careers page. $2 per 1,000 listings, first 50 free on every run. Detects the ATS behind each site - Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Rippling, Breezy, Personio, BambooHR - and reads its public endpoint. No tokens, no proxies.

- **URL**: https://apify.com/om\_kh/careers-page-scraper.md
- **Developed by:** [omar khandji](https://apify.com/om_kh) (community)
- **Categories:** Jobs, Lead generation, MCP servers
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 job listings

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Careers Page Scraper — Company Domain to Open Jobs

> **You paste `stripe.com`. You get all 545 open roles.**
>
> One input: company websites. The Actor works out which applicant tracking
> system sits behind each careers page and reads that system's own public
> endpoint. No tokens to look up, no provider to choose, no proxies.
> **10 job listings free on every run.**

### Measured, on real companies

| You paste | It finds | You get |
| --- | --- | --- |
| `stripe.com` | Greenhouse | 545 roles |
| `anthropic.com` | Greenhouse | 399 roles |
| `figma.com` | Greenhouse | 177 roles |
| `ramp.com` | Ashby | 123 roles |
| `notion.so` | Ashby | 110 roles |
| `vercel.com` | Greenhouse | 81 roles |
| `monzo.com` | Greenhouse | 75 roles |

*(2026-08-03 — 1,550 live roles from eight bare domains, nothing else supplied.)*

### How it finds the ATS

Two passes. It reads the company's careers page and looks at where it links —
`boards.greenhouse.io/stripe`, `jobs.lever.co/figma` — and if nothing is linked
it derives the likely handle from the domain and asks the providers directly.

Nine systems are supported: **Greenhouse, Lever, Ashby, Workday,
SmartRecruiters, Rippling, Breezy HR, Personio, BambooHR**.

A company running its own careers page with no hosted ATS behind it comes back
with `"ats": null` and no rows — an answer, not an error.

### Why not scrape a job board

Job aggregators mean cookies, proxies, rate limits, and roles that are stale or
reposted by three agencies. This reads the employer's own feed.

| | Aggregator scraper | This Actor |
| --- | --- | --- |
| What breaks it | anti-bot, layout changes, expired cookies | nothing — these are the companies' own public endpoints |
| Freshness | an aggregator's copy | the role as the employer published it |
| Duplicates | the same role three times | one row per role |
| Proxy bill | yes | none |

### Filter before you pay

Filters run **before billing**, so you are never charged for a job you excluded.

| Input | Effect |
| --- | --- |
| `keywords` | Keep jobs whose title, department, company or location contains one of these |
| `excludeKeywords` | Drop jobs matching any of these — `intern`, `senior`, `sales` |
| `locations` | Keep jobs whose location contains one of these |
| `remoteOnly` | Keep only roles whose location says remote, anywhere or distributed |
| `postedAfter` | Keep jobs posted on or after `YYYY-MM-DD` |

**Keywords match whole words and do not stem.** `engineer` returns "Backend
Engineer" but not "Engineering Intern" — pass both if you want both. A substring
filter for `ai` would match "m**ai**ntainer", which on a real board kept 40% of
unrelated roles.

### Output

```json
{
  "domain": "stripe.com",
  "source_url": "https://boards.greenhouse.io/stripe/jobs/6789",
  "title": "Account Executive, AI Sales",
  "company": "stripe",
  "location": "New York",
  "department": "Sales",
  "posted_at": "2026-07-20T09:12:00Z",
  "source": "greenhouse",
  "function": "Sales",
  "seniority": "Mid"
}
```

Roles are deduplicated by URL, so two domains resolving to the same board never
bill you twice. **Seniority and job function are inferred and attached.**

### What a run costs

Two parts, and the second is the one that keeps this Actor alive:

| | |
|---|---|
| **$0.04 per search** | one run, charged only when the run delivered at least one job |
| **$2 per 1,000 job listings** | $0.002 each, and only for listings actually delivered to you |

The search fee exists because a run costs real compute whether it returns six
rows or six hundred. It is flat, so **batching is the cheap way to use this
Actor**: fifty companies in one run pay the fee once.

A run that finds nothing is never charged at all.

> **The $0.04 search fee starts on 24 August 2026.** Apify requires two
> weeks' notice before an existing user pays a charge they did not pay
> before, so until that date every run is billed on job listings alone.

### Free tier — 10 job listings on every run

**The first 10 job listings of every run are free**, on every run you ever make,
not just the first. Wire it into a pipeline and evaluate it on your own target
companies before a cent is billed.

The free allowance never covers more than half of a run, so a run returning 20
listings gets 10 free rather than 20 — that is what stops it becoming an
unlimited free plan for anyone willing to split one job into many tiny runs.

### Pricing

**$0.002 per job listing — $2 per 1,000**, after the free 10.

Same price as the [ATS Jobs API](https://apify.com/om_kh/ats-jobs-api), which
reads the same endpoints and returns the same rows with more control over
providers and deltas.

### Limits

- **100 companies per run**, **15 per request** in HTTP mode, so a request
  finishes inside Apify's five-minute ceiling.
- Workday pages 20 roles at a time and is capped at 200 roles per tenant.

### Use it from an AI agent (MCP)

This Actor is a **Model Context Protocol server**. Point any MCP client at it and
the tool appears with its full input schema — no wrapper code:

```
https://om-kh--careers-page-scraper.apify.actor/mcp
```

```json
{
  "mcpServers": {
    "careers_page_jobs": {
      "url": "https://om-kh--careers-page-scraper.apify.actor/mcp",
      "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
    }
  }
}
```

One tool, `careers_page_jobs`. It takes the same arguments as the Start form and returns the
same rows, so an agent and a `curl` user can never get different answers.

### Related scrapers

Same data, other sources — all with the same free tier, the same clean schema and the same pay-only-for-what-you-get billing:

| Actor |
|---|
| [ATS Jobs API | $2/1K | Any Company Domain, 10 Free](https://apify.com/om_kh/ats-jobs-api) |
| [Hiring Signals | $0.02/company | Buying Triggers](https://apify.com/om_kh/company-hiring-signals) |
| [Indeed Jobs Scraper - Listings, Companies & Salary](https://apify.com/om_kh/vigia-indeed-hiring-monitor) |
| [LinkedIn Jobs Scraper - Listings & Companies](https://apify.com/om_kh/vigia-linkedin-jobs-monitor) |
| [Glassdoor Reviews Scraper - Employer Ratings](https://apify.com/om_kh/vigia-glassdoor-review-monitor) |
| [LinkedIn Company Scraper - Followers & Headcount](https://apify.com/om_kh/vigia-linkedin-company-monitor) |

# Actor input Schema

## `companyDomains` (type: `array`):

The company websites you want jobs from. Just the domain - stripe.com, figma.com. The Actor works out which applicant tracking system each one uses. Max 100 per run.

## `keywords` (type: `array`):

Keep only jobs whose title, department, company or location contains one of these words. Whole-word match. Filtering happens before billing - you are never charged for a job you filtered out.

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

Drop jobs matching any of these words, e.g. intern, senior, sales.

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

Keep only jobs whose location contains one of these, e.g. Berlin, United Kingdom.

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

Keep only roles whose location says remote, anywhere or distributed.

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

Keep only jobs posted on or after this date (YYYY-MM-DD). Jobs from providers that publish no date are kept.

## `maxTotalChargeUsd` (type: `number`):

Hard ceiling on what this run can bill you. The run stops delivering paid rows once it is reached.

## Actor input object example

```json
{
  "companyDomains": [
    "stripe.com",
    "figma.com",
    "notion.so"
  ],
  "remoteOnly": false,
  "maxTotalChargeUsd": 1
}
```

# Actor output Schema

## `results` (type: `string`):

Every row this run delivered, as JSON. You are billed only for rows that reach this dataset.

## `runSummary` (type: `string`):

What the run actually did: rows delivered, rows charged, free results granted, the exact amount billed, and any source that failed.

# 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 = {
    "companyDomains": [
        "stripe.com",
        "figma.com",
        "notion.so"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("om_kh/careers-page-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 = { "companyDomains": [
        "stripe.com",
        "figma.com",
        "notion.so",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("om_kh/careers-page-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 '{
  "companyDomains": [
    "stripe.com",
    "figma.com",
    "notion.so"
  ]
}' |
apify call om_kh/careers-page-scraper --silent --output-dataset

```

## MCP server setup

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