# Career Page Jobs Scraper: Greenhouse, Lever, Ashby (`toowettodrip/career-page-jobs`) Actor

Collect open jobs straight from company career pages that run on Greenhouse, Lever, Ashby or Workable. Paste career-page links and get clean rows: title, team, location, remote, pay range, dates and apply link. Switch on only-new to pay just for jobs you have not seen before.

- **URL**: https://apify.com/toowettodrip/career-page-jobs.md
- **Developed by:** [Cameron Causey](https://apify.com/toowettodrip) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

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: Greenhouse, Lever, Ashby, Workable

Collect open jobs straight from company career pages and get them back in one clean format, whichever hiring system the company uses.

Many companies run their careers page on Greenhouse, Lever, Ashby or Workable. Each of those systems publishes the company's open jobs as a public list, with no login. This tool reads those public lists for the companies you name and returns one tidy row per job.

### What you get

One row per open job, with the same fields for every company:

- company, job title, department and team
- location, every other listed location, country
- remote or not, and the workplace type (remote, hybrid, on-site) when the company states it
- job type (full-time, internship and so on)
- date posted, and date updated when the system gives one
- link to the job and link to apply
- pay range when the company publishes one: lowest, highest, currency and period
- the full description as plain text (optional), and as HTML (optional)

### How to use it

1. **List the companies.** Paste the address of each company's jobs page, one per line. For example `https://boards.greenhouse.io/stripe`, `https://jobs.lever.co/palantir`, `https://jobs.ashbyhq.com/ramp` or `https://apply.workable.com/huggingface`. The short form `greenhouse:stripe` works too. Leave the list empty to try the tool on a small built-in starter list.
2. **Narrow it down (optional).** Keep only titles that contain certain words, drop titles that contain others, keep only certain locations, only remote jobs, or only jobs posted in the last N days. You can also cap the number of jobs per company.
3. **Run it.** Results appear in the dataset, ready to export as JSON, CSV or Excel, or to read through the API.

#### Only what is new

Switch on **Only jobs that are new since the last run** and put the tool on a schedule. The first run returns everything that matches. Every later run returns only jobs it has not given you before, so a daily check hands you just the new openings and you pay only for those. A job that closes and later reopens counts as new again.

### Example result

```json
{
  "company": "Ramp",
  "source": "ashby",
  "companyId": "ramp",
  "id": "34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "title": "Security Engineer, Cloud",
  "department": "Engineering",
  "team": "Backend",
  "location": "New York, NY (HQ)",
  "allLocations": ["New York, NY (HQ)", "Remote (Canada)"],
  "country": "USA",
  "remote": true,
  "workplaceType": "hybrid",
  "employmentType": "FullTime",
  "postedAt": "2026-04-07T17:12:35.753Z",
  "updatedAt": null,
  "url": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245",
  "applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application",
  "salaryMin": 211400,
  "salaryMax": 290600,
  "salaryCurrency": "USD",
  "salaryInterval": "1 YEAR",
  "salaryText": "$211.4K - $290.6K",
  "descriptionText": "ABOUT RAMP ...",
  "scrapedAt": "2026-10-08T07:00:00.000Z"
}
```

Fields a hiring system does not provide come back as `null`. Greenhouse and Workable do not publish pay as separate numbers, so the pay fields are empty for those companies.

### Price

You pay per job returned: **$1.50 per 1,000 jobs**, plus a start fee of a fraction of a cent per run. A run that returns 200 jobs costs about $0.30. Jobs removed by your filters are not charged, and with the only-new switch on, jobs you have already received are not charged again. If you set a spending limit for a run, the tool stops when it is reached and tells you so.

### What it does not do

- It reads only the public job lists that the hiring systems publish. It does not log in anywhere and does not get around any block.
- It does not collect recruiter names, email addresses or any other personal details.
- It does not cover companies whose careers page runs on another system. A line it cannot read is skipped, and the run log says which line and why.
- It makes about one request a second to each hiring system, so very long company lists take a little time.

Job descriptions are written by the employers and remain theirs. Use them for your own search, research or analysis. If you plan to republish them, check that you are allowed to.

### Common questions

**How do I find the right address?** Open the company's careers page and click through to the list of open roles. If the address contains `greenhouse.io`, `lever.co`, `ashbyhq.com` or `workable.com`, paste it in.

**A company returns nothing.** It may have no open roles, or its careers page may run on a different system. The run log explains each skipped line, and the `SUMMARY` record in the key-value store lists every company that could not be read.

**How fresh is the data?** Each run reads the live list, so results match what the career page shows at that moment.

**Something is wrong or missing.** Open an issue on the Issues tab with the company address you used. Issues are answered there.

This tool is not affiliated with or endorsed by Greenhouse, Lever, Ashby or Workable.

# Actor input Schema

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

One per line. Paste the career page address (for example https://boards.greenhouse.io/stripe, https://jobs.lever.co/palantir, https://jobs.ashbyhq.com/ramp, https://apply.workable.com/huggingface) or use the short form system:name (greenhouse:stripe, lever:palantir, ashby:ramp, workable:huggingface). Leave empty to try the tool on a built-in starter list.

## `titleIncludes` (type: `array`):

Keep a job only if its title contains at least one of these words or phrases. Not case sensitive. Leave empty to keep every title.

## `titleExcludes` (type: `array`):

Drop a job if its title contains any of these words or phrases. Not case sensitive.

## `locationIncludes` (type: `array`):

Keep a job only if one of its locations contains at least one of these words (for example a city, state or country). Not case sensitive. Leave empty to keep every location.

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

Keep only jobs the company marks as remote.

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

Keep only jobs published in the last N days. 0 keeps every job. Jobs without a publish date are kept.

## `onlyNewSinceLastRun` (type: `boolean`):

Remembers which jobs it has already returned for you and returns only the ones it has not seen before. Useful on a schedule: each run gives you just the new openings. The first run returns everything.

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

Adds the job description as plain text. Turn off for smaller, faster results.

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

Adds the original formatted description. Only used when the full description is included.

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

Stop after this many matching jobs for each company. 0 means no limit.

## Actor input object example

```json
{
  "companies": [
    "greenhouse:stripe",
    "lever:palantir",
    "ashby:ramp",
    "workable:huggingface"
  ],
  "titleIncludes": [],
  "titleExcludes": [],
  "locationIncludes": [],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "onlyNewSinceLastRun": false,
  "includeDescription": true,
  "includeDescriptionHtml": false,
  "maxJobsPerCompany": 0
}
```

# Actor output Schema

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

All job rows collected by this run.

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

Counts per company and the list of companies that could not be read.

# 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": [
        "greenhouse:stripe",
        "lever:palantir",
        "ashby:ramp",
        "workable:huggingface"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("toowettodrip/career-page-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": [
        "greenhouse:stripe",
        "lever:palantir",
        "ashby:ramp",
        "workable:huggingface",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("toowettodrip/career-page-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": [
    "greenhouse:stripe",
    "lever:palantir",
    "ashby:ramp",
    "workable:huggingface"
  ]
}' |
apify call toowettodrip/career-page-jobs --silent --output-dataset

```

## MCP server setup

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