# Careers Page Scraper — Jobs from Any Company Site, Any ATS (`highbrow_fame/careers-page-jobs-api`) Actor

Give career page or ATS board URLs; get open jobs with title, location, department, remote flag, description and apply URL. Greenhouse, Lever, Ashby, Workable and more. Unofficial Careers Page API.

- **URL**: https://apify.com/highbrow_fame/careers-page-jobs-api.md
- **Developed by:** [yestrue](https://apify.com/highbrow_fame) (community)
- **Categories:** Jobs, AI, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.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

## Careers Page Scraper — Jobs from Any Company Site, Any ATS

Every open job from any company's careers page as clean JSON — title, location, department, remote flag, employment type, salary when published, posting date, full description and apply link. Paste a careers page, a company domain or an ATS board link; the Actor finds the applicant tracking system behind it (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee or Personio) and reads its public job feed. No HTML guessing, no logins, no personal data.

**Try it in 1 minute:**

1. Press **Start** — the prefilled input reads three public boards (Greenhouse, Lever, Ashby).
2. In about 10 seconds the **Output** tab lists every open job of those companies, one record each, with apply links.
3. Download it as JSON, CSV or Excel, or call the Actor from your code or AI agent.

Price: $1.00 per 1,000 jobs. Companies without a supported ATS, empty boards and filtered-out jobs are free.

**Use it to:**

- Build a job board or newsletter from the companies you follow — one scheduled run a day, only the boards you choose.
- Feed an AI job-search agent with structured, current openings instead of scraped HTML.
- Track hiring signals: which teams and locations a competitor or a portfolio company is hiring for, week over week.
- Fill a recruiting CRM or a spreadsheet with openings, departments and salary ranges across hundreds of companies.
- Research the remote-work market: filter to remote jobs by keyword across any list of employers.

### How it works

1. **Recognise the board.** A link like `boards.greenhouse.io/<company>`, `jobs.lever.co/<company>`, `jobs.ashbyhq.com/<company>`, `apply.workable.com/<company>`, `careers.smartrecruiters.com/<Company>`, `<company>.recruitee.com` or `<company>.jobs.personio.de` is read directly. A careers page or a bare domain (`acme.com`, plus its `/careers` and `/jobs` pages) is scanned for the ATS it links to, embeds or loads.
2. **Read the public feed.** Each ATS publishes its open jobs as JSON (Personio as XML) for its own careers widget; the Actor reads that feed — complete, current and without a browser.
3. **Normalise.** Jobs from every ATS come out in one shape: ISO dates, a `remote` flag (from the ATS's own flag or the location text), locations as a list, plain-text descriptions with e-mail addresses and phone numbers removed.
4. **Filter and deliver.** Optional title keywords, location texts and *remote only* narrow the list before anything is charged.

Teamtailor, Workday and BambooHR boards are recognised but not read — they have no public list endpoint; such companies come back as `UNSUPPORTED_ATS`, free.

### Input

| Field | What it does |
|---|---|
| `companies` | Careers pages, company domains or ATS board links, one per line. Required. |
| `maxJobsPerCompany` | Stop each company after this many jobs (default 500). |
| `keywords` | Keep only titles containing any of these words (case-insensitive). |
| `locations` | Keep only jobs whose location contains any of these texts. |
| `remoteOnly` | Keep only jobs flagged remote or whose location says Remote / Anywhere. |
| `includeDescription` | Plain-text description with contacts removed (default on). Workable and SmartRecruiters need one extra request per job for it. |
| `maxDescriptionLength` | Cut descriptions after N characters (default 20,000; 0 = no limit). |
| `maxConcurrency`, `proxyConfiguration` | Speed and retries. The first request goes out directly; the proxy is used only to retry after a network error. |

### Output

One record per job:

| Field | What it is |
|---|---|
| `company`, `ats` | Company slug or name, and the ATS it was read from |
| `id`, `title`, `url`, `applyUrl` | The job, its public page and where to apply |
| `location`, `locations` | Primary location and all locations when there are several |
| `department`, `team`, `employmentType` | Department, team and full-time / part-time / contract as the ATS words it |
| `remote` | `true`, `false` or `null` (unknown) |
| `postedAt` | ISO 8601 publish or last-update time |
| `description` | Plain text, e-mails and phones removed |
| `salary` | Compensation range as text when the ATS publishes one |
| `input`, `position`, `status`, `error`, `scrapedAt` | What you gave, the job's place in its company, and why an input gave nothing |

A company that gives no job gets one free record with `status` = `NOT_FOUND`, `UNSUPPORTED_ATS`, `NO_RESULTS`, `INVALID_INPUT` or `FAILED` and a plain-language `error`.

#### Example

```json
{
  "input": "https://boards.greenhouse.io/examplecorp",
  "company": "examplecorp",
  "ats": "greenhouse",
  "id": "4011223344",
  "title": "Senior Backend Engineer, Payments",
  "location": "Remote - United States",
  "locations": ["San Francisco", "New York"],
  "department": "Engineering",
  "team": null,
  "employmentType": "Full-time",
  "remote": true,
  "url": "https://boards.greenhouse.io/examplecorp/jobs/4011223344",
  "applyUrl": "https://boards.greenhouse.io/examplecorp/jobs/4011223344",
  "postedAt": "2026-09-30T13:00:00.000Z",
  "description": "We are hiring a Senior Backend Engineer for our payments platform.\n- Go or Java\n- Questions? Write to [e-mail removed]",
  "salary": null,
  "position": 1,
  "status": "OK",
  "scrapedAt": "2026-10-19T12:00:00.000Z"
}
```

### FAQ

**Is this an official API?** No, it's an unofficial API built on public pages — the same public job feeds each ATS serves to its own careers widgets.

**Which ATS are supported?** Greenhouse (including EU boards and embedded boards), Lever (including EU), Ashby, Workable, SmartRecruiters, Recruitee and Personio. Teamtailor, Workday and BambooHR are detected but not read, and come back free as `UNSUPPORTED_ATS`.

**My company's careers page came back `NOT_FOUND`.** The page does not link to a supported ATS — it may use a custom job list or one of the unsupported systems. Try the ATS board link directly if you know it (open a job on the careers page and look at the address).

**Do you collect recruiter names or contact details?** No. Descriptions are delivered as plain text with e-mail addresses and phone numbers removed, and no person names are collected.

**How current is the data?** Each run reads the live feed, so you get what the company shows right now. Schedule the Actor daily to follow changes.

**Like it?** A short review on the Store page helps other people find this Actor. Something missing or broken? Tell us on the Issues tab — we read every one.

### Related Actors

- [Remote Jobs Scraper](https://apify.com/highbrow_fame/remote-jobs-aggregator) — remote jobs from Himalayas, Remote OK and more
- [Google Maps Email Extractor & Lead Scraper](https://apify.com/highbrow_fame/google-maps-email-extractor) — business leads with emails from Google Maps
- [Website Tech Stack Detector](https://apify.com/highbrow_fame/website-tech-stack) — CMS, frameworks and analytics of any site
- [Web Fetch API](https://apify.com/highbrow_fame/web-fetch-api) — Fetch any URL as HTML, text, Markdown or JSON

# Actor input Schema

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

One per line: a company careers page, a company domain (acme.com), or an ATS board link — boards.greenhouse.io/…, jobs.lever.co/…, jobs.ashbyhq.com/…, apply.workable.com/…, careers.smartrecruiters.com/…, <company>.recruitee.com, <company>.jobs.personio.de. A careers page is scanned for the ATS it embeds.

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

Stops each company after this many jobs.

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

Optional. Keep only jobs whose title contains any of these words (case-insensitive), e.g. "engineer", "data". Filtered-out jobs are free.

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

Optional. Keep only jobs whose location contains any of these texts, e.g. "London", "United States", "Remote".

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

Keep only jobs the ATS marks as remote, or whose location says Remote / Anywhere / Work from home.

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

Include the job description as plain text. E-mail addresses and phone numbers in it are removed. Off: smaller records and fewer requests (Workable and SmartRecruiters need one extra request per job for the description).

## `maxDescriptionLength` (type: `integer`):

Cut the description after this many characters. 0: no limit.

## `maxConcurrency` (type: `integer`):

How many companies to read at the same time.

## `proxyConfiguration` (type: `object`):

Used only to try again after a network error: the first try goes out directly.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/airbnb",
    "https://jobs.lever.co/netflix",
    "https://jobs.ashbyhq.com/openai"
  ],
  "maxJobsPerCompany": 100,
  "remoteOnly": false,
  "includeDescription": true,
  "maxDescriptionLength": 20000,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

Every result as a JSON record, with a status for each input.

## `resultsCsv` (type: `string`):

The same records as CSV, for a spreadsheet.

# 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/airbnb",
        "https://jobs.lever.co/netflix",
        "https://jobs.ashbyhq.com/openai"
    ],
    "maxJobsPerCompany": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("highbrow_fame/careers-page-jobs-api").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/airbnb",
        "https://jobs.lever.co/netflix",
        "https://jobs.ashbyhq.com/openai",
    ],
    "maxJobsPerCompany": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("highbrow_fame/careers-page-jobs-api").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/airbnb",
    "https://jobs.lever.co/netflix",
    "https://jobs.ashbyhq.com/openai"
  ],
  "maxJobsPerCompany": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call highbrow_fame/careers-page-jobs-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,highbrow_fame/careers-page-jobs-api"
        }
    }
}
```

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/Uygr9R5DoNfXL5w5o/builds/AfD5ruWKqjGm8OzR1/openapi.json
