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

Give company domains, get every open job from their own career site: Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio. One schema, salary where published, filters, and a monitor for new and closed jobs. $1.50 per 1,000 jobs.

- **URL**: https://apify.com/ninoventures/career-site-jobs.md
- **Developed by:** [Nino Ventures](https://apify.com/ninoventures) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 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: Greenhouse, Lever, Ashby & more

Give it a list of companies and get every open job from their own career sites, in one table with the same columns for every company. It works with Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee and Personio.

You don't have to know which system a company uses. Enter `stripe.com` and the actor finds the job board itself.

Good for job boards and aggregators, recruiters tracking target companies, sales teams using hiring as a buying signal, and anyone building a job feed for an AI agent.

### Input

- **Companies**: a domain (`ramp.com`), a careers page URL, or a job board URL (`boards.greenhouse.io/discord`, `jobs.lever.co/palantir`, `jobs.ashbyhq.com/ramp`).
- Optional filters: title keywords, excluded title keywords, location keywords, remote only, posted in the last N days.
- **Include full job description**: plain text, at the same price.
- **Only output jobs not seen in earlier runs**: monitoring mode, explained below.

### How it finds the job board

1. If you give a job board URL, it uses that.
2. Otherwise it opens the company's `/careers`, `/jobs` and homepage, plus `careers.` and `jobs.` subdomains, and looks for links or embeds of a supported job board.
3. If that finds nothing, it tries the company name as the board ID, for example `stripe.com` -> `greenhouse/stripe`. A guessed Greenhouse board is only used when its job links or board name match the company.

Every row has `matchedBy` (`url`, `careers-page` or `name-guess`), so you can see how each board was found.

### Output (one row per job)

`company`, `title`, `department`, `location`, `country`, `remote`, `workplaceType`, `employmentType`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryText`, `postedAt`, `updatedAt`, `url`, `applyUrl`, `ats`, `boardId`, `jobId`, `isNewSinceLastRun`, and `description` when you turn it on.

Salary is filled only when the company publishes it on the board. That is mostly Greenhouse pay ranges and Ashby compensation, so mainly US roles.

### Numbers from our test run (31 Oct 2026)

Input: 20 company domains, all jobs, no filters (airbnb.com, stripe.com, ramp.com, palantir.com, notion.so, gitlab.com, doctolib.fr, bunq.com, n26.com and others).

- 17 of 20 companies resolved. Revolut, Canva and Personio did not use a supported board. (An earlier build wrongly matched personio.com to a 1-job Recruitee test board; that guess is now rejected.)
- 2,749 open jobs in 2 min 40 s. Platform cost for the run: about $0.02.
- By job board: Greenhouse 1,699, Ashby 404, SmartRecruiters 314, Lever 301, Recruitee 26, Workable 6.
- 623 jobs (23%) had a salary range: 535 in USD, 25 EUR, 21 CAD, 16 GBP and a few others.
- 674 marked remote. 1,009 posted in October 2026.
- Stripe alone: 745 open jobs.

### Monitoring: new and closed jobs

Turn on **Only output jobs not seen in earlier runs** and schedule the actor daily.

- The first run stores every job ID per company as a baseline.
- Each later run outputs only newly posted jobs.
- The `SUMMARY` record in the key-value store lists, per company, how many jobs are open, new and closed, with the titles of up to 100 closed jobs.

Use **Monitor name** to keep separate lists, for example one per client or per sales territory.

### Pricing

**$1.50 per 1,000 jobs saved.** No monthly fee and no charge per run.

Jobs removed by your filters cost nothing, and so do already-seen jobs in monitoring mode. A daily monitor on 50 companies that post 20 new jobs a day in total costs about $0.90 a month.

### Limits

- Only the seven job boards above. Companies on Workday, iCIMS, Taleo, SuccessFactors or their own system come back as "no supported job board found", at no charge.
- Workable rate-limits its public API. The actor waits and retries, so Workable companies are slower.
- A company that uses one of these boards for only part of its hiring will show only that part.

### Data and terms

The actor uses the public job board endpoints that these systems provide so companies can show openings on their own websites. No login, no candidate data, and no personal data beyond what a company publishes in a job ad.

### Feedback

Missing a company or a job board? Open an issue with the domain and we'll look at it.

# Actor input Schema

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

One per line: a company domain (stripe.com), its careers page URL, or a job board URL (boards.greenhouse.io/discord, jobs.lever.co/palantir, jobs.ashbyhq.com/ramp). The actor finds which job board the company uses.

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

Case-insensitive. Empty = all jobs. Example: engineer, data, sales.

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

Example: intern, senior.

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

Matched against the job location text and country code. Example: London, Remote, DE.

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

Keeps jobs the board marks as remote or whose location says remote.

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

0 = no filter.

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

Plain text. Makes the dataset much bigger. Same price.

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

Stops after this many jobs per company (after filters). Stripe alone had 745 open jobs in our test.

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

Monitoring mode. The first run sets the baseline per company. Later runs output only newly posted jobs, and the SUMMARY record lists jobs that were closed.

## `monitorName` (type: `string`):

Separate memory per watch list.

## `guessBoardFromName` (type: `boolean`):

For example stripe.com -> greenhouse/stripe. Guessed Greenhouse boards are only used when the job links or board name match the company. Every row says how the board was found in matchedBy.

## Actor input object example

```json
{
  "companies": [
    "stripe.com",
    "ramp.com",
    "palantir.com",
    "bunq.com"
  ],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": false,
  "maxJobsPerCompany": 1000,
  "onlyNewJobs": false,
  "guessBoardFromName": true
}
```

# Actor output Schema

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

No description

## `summary` (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": [
        "stripe.com",
        "ramp.com",
        "palantir.com",
        "bunq.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ninoventures/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": [
        "stripe.com",
        "ramp.com",
        "palantir.com",
        "bunq.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("ninoventures/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": [
    "stripe.com",
    "ramp.com",
    "palantir.com",
    "bunq.com"
  ]
}' |
apify call ninoventures/career-site-jobs --silent --output-dataset

```

## MCP server setup

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