# Lever Jobs Scraper: Export Any Lever Job Board (`pulsedata/lever-jobs-scraper`) Actor

Scrape all open jobs from any Lever job board (jobs.lever.co): title, location, workplace type, team, department, commitment, posting date, published salary range, full description and apply URL. No API key. $2.00 per 1,000 jobs.

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

## Pricing

$2.00 / 1,000 job scrapeds

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

## Lever Jobs Scraper: Export Any Lever Job Board

Lever Jobs Scraper exports every open posting from one or more Lever job boards (`jobs.lever.co`) as JSON, CSV or Excel. You give it board URLs or just company names such as `spotify`, and it returns one record per job with title, all locations, country, workplace type, team, department, commitment, the published salary range, the full description and separate job and apply URLs. It costs $2.00 per 1,000 jobs, so a 500-job board costs about $1.00.

### Features

- **Scrape Lever job boards** by URL or by company name. A bare name like `palantir` is expanded to `https://jobs.lever.co/palantir`.
- **Export jobs.lever.co postings to CSV, JSON or Excel**, including the description and every list section (responsibilities, requirements and so on).
- **Get Lever salary ranges.** Lever's postings API carries a structured salary range, which many US boards fill in because of pay transparency laws.
- **Scrape EU Lever boards** on `jobs.eu.lever.co`, read from Lever's EU API.
- **Filter Lever jobs by keyword, location, country, remote and posting date.**
- **Find remote jobs on Lever** using Lever's own workplace type (`remote`, `hybrid`, `on-site`).
- **No API key and no login.** Lever publishes every board through its public postings API.

### Use cases

- **Job board aggregation:** refresh openings from a list of Lever companies every morning.
- **Salary benchmarking:** collect published ranges for one job family (for example "Data Scientist") across dozens of Lever employers.
- **Recruiting and sourcing:** watch which Lever teams a competitor is growing and whether roles are remote, hybrid or on-site.
- **Lead generation:** companies opening sales or security roles often buy tooling for those teams; filter by `keywords` and run weekly.

### Input

```json
{
  "startUrls": [
    "https://jobs.lever.co/spotify",
    "palantir",
    "https://jobs.eu.lever.co/examplecompany"
  ],
  "keywords": ["data", "machine learning"],
  "locations": ["New York", "London", "US"],
  "remoteOnly": true,
  "postedWithinDays": 30,
  "includeDescription": true,
  "maxJobsPerCompany": 100
}
```

| Field | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | array of strings | (required) | Lever board URLs or bare company names, one per line. |
| `keywords` | array | `[]` | Keep only jobs whose title contains one of these words (case-insensitive). |
| `locations` | array | `[]` | Keep only jobs whose location, any of its other locations, or its country code contains one of these strings. |
| `remoteOnly` | boolean | `false` | Keep only jobs Lever marks as `remote`, or whose location mentions remote. |
| `postedWithinDays` | integer | `0` | Keep only jobs created in the last N days. 0 means no limit. |
| `includeDescription` | boolean | `true` | Include `descriptionHtml` and `descriptionText`. Lever returns them in the same request, so this adds no extra requests. |
| `maxJobsPerCompany` | integer | `0` | Cap per board, applied after the filters. 0 means no limit. |
| `proxyConfiguration` | object | `{ "useApifyProxy": false }` | Optional Apify Proxy. |

**Accepted Lever URL formats:**

- `https://jobs.lever.co/spotify`
- `https://jobs.lever.co/spotify/<posting-id>` (a single posting URL; the actor still reads the whole board)
- `https://jobs.eu.lever.co/company` (EU-hosted boards)
- `spotify` (bare company name, always expanded to the US host, so use the full URL for EU boards)
- `https://company.com/careers` (a page that links to a Lever board)

### Output

One item per job:

```json
{
  "title": "Data Scientist - Music Mission",
  "company": "spotify",
  "location": "New York",
  "locations": ["New York", "Boston"],
  "country": "US",
  "remote": true,
  "workplaceType": "remote",
  "department": "Data",
  "team": "Music Mission",
  "employmentType": "Permanent",
  "seniority": null,
  "salary": "116994-167135 USD per-year-salary",
  "postedAt": "2026-06-23T11:29:45.805Z",
  "updatedAt": null,
  "url": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1",
  "applyUrl": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1/apply",
  "descriptionHtml": "<div>The Music Mission team…</div>\n<h3>What you'll do</h3><ul><li>…</li></ul>",
  "descriptionText": "The Music Mission team…\n\nWhat you'll do\n…",
  "ats": "lever",
  "atsJobId": "2193db3f-77c5-43b8-b030-8f92c9882bf1",
  "sourceUrl": "https://jobs.lever.co/spotify",
  "scrapedAt": "2026-09-25T08:20:44.000Z"
}
```

What Lever exposes, and how it maps:

- `company` is the Lever company name from the URL (for example `spotify`).
- `location` is the primary location; `locations` is Lever's full list of locations for the posting.
- `country` is the ISO country code Lever stores on the posting.
- `workplaceType` is Lever's value as published (`remote`, `hybrid`, `on-site` or `unspecified`). `remote` is `true` when it is `remote` or the location text says remote.
- `department` and `team` are Lever's two category levels; `employmentType` is Lever's "commitment" (for example `Full-time`, `Permanent`, `Intern`).
- `salary` is built from Lever's salary range as `min-max currency interval`. When a board does not publish a range, the actor looks for one near the start of the description.
- `descriptionHtml` joins the opening text, each list section (with its heading) and the closing text.
- `postedAt` is the posting's creation date in Lever. Lever has no separate update date, so `updatedAt` is `null`; `seniority` is also not published.

If a company name does not exist on Lever, the dataset gets one row with `sourceUrl`, `ats`, `slug` and an `error` message. Error rows are not charged.

### Pricing

Pay per event: **$0.002 per job** saved to the dataset ($2.00 per 1,000 jobs). There is no start fee.

Worked example: a salary study across 60 Lever companies with around 80 postings each is 4,800 jobs, or $9.60 for a full export. If you only need engineering roles and set `keywords: ["engineer", "developer"]`, you might keep 1,500 jobs and pay $3.00. Jobs removed by filters and error rows are not charged.

### FAQ

**Do I need an API key or a Lever login?**
No. Lever job boards are public and the actor reads the public postings API behind them.

**Does every job include a salary?**
No. The range is filled only when the company publishes one in Lever, or when a range appears near the start of the description. US boards publish it more often than European ones.

**How many jobs can it get from one board?**
The whole board. Lever returns all published postings in one response; `maxJobsPerCompany` limits the output if you want less.

**What can it not do?**
It only sees postings the company lists publicly. Unlisted or internal postings, application forms and candidate data are out of reach. It does not render JavaScript, so if your careers page loads Lever through a script, paste the `jobs.lever.co` URL instead.

**Do I need proxies?**
Normally no. The actor backs off and retries on rate limits and server errors. Enable `proxyConfiguration` only if a very large list starts returning HTTP 429.

**Can I mix Lever with other ATS in one run?**
Use the [Career Page Jobs Scraper](https://apify.com/pulsedata/career-page-jobs-scraper) for that. It auto-detects Lever, Greenhouse, Ashby, Workday and eight other systems.

**How do I export, schedule or automate it?**
Download results as JSON, CSV, Excel, XML or HTML, start runs from the Apify API or SDKs, schedule them in Apify Console, or connect the actor to Google Sheets, Make, Zapier or n8n.

### Related actors

- [Career Page Jobs Scraper (12 ATS)](https://apify.com/pulsedata/career-page-jobs-scraper): multi-ATS version with auto-detection for mixed company lists.
- [Greenhouse Jobs Scraper](https://apify.com/pulsedata/greenhouse-jobs-scraper): the same output for Greenhouse boards, the most common ATS among mid-size tech companies.
- [Ashby Jobs Scraper](https://apify.com/pulsedata/ashby-jobs-scraper): Ashby boards, which also publish compensation.
- [Workday Jobs Scraper](https://apify.com/pulsedata/workday-jobs-scraper): enterprise careers sites on `myworkdayjobs.com`.
- [Website Tech Stack Detector](https://apify.com/pulsedata/website-tech-stack-detector): enrich the hiring companies with the technologies their websites use.

# Actor input Schema

## `startUrls` (type: `array`):

Lever board URLs such as `https://jobs.lever.co/spotify` (EU boards: `https://jobs.eu.lever.co/<company>`), or just the company name (`spotify`). A company's own careers page works too when it links a Lever board.

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

Only keep jobs whose title contains at least one of these words/phrases (case-insensitive). Leave empty for all jobs.

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

Only keep jobs whose location contains one of these strings (e.g. `Berlin`, `Germany`, `Remote`, `United States`).

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

Keep only jobs flagged as remote by the ATS or whose location mentions remote.

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

Only jobs posted or updated within the last N days. Jobs whose ATS publishes no date are kept. 0 = no limit.

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

Return the full description (HTML + plain text). For Workday, SmartRecruiters, BambooHR, Workable and Breezy this requires one extra request per job.

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

Maximum jobs returned per career page, counted after the keyword, location, remote and date filters (0 = no limit).

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

Optional. ATS APIs are public and rarely block; enable Apify Proxy only if you hit rate limits.

## Actor input object example

```json
{
  "startUrls": [
    "https://jobs.lever.co/spotify",
    "palantir"
  ],
  "keywords": [],
  "locations": [],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": true,
  "maxJobsPerCompany": 0,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Results stored in the default dataset (JSON/CSV/Excel via the dataset API).

# 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 = {
    "startUrls": [
        "https://jobs.lever.co/spotify",
        "palantir"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pulsedata/lever-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 = { "startUrls": [
        "https://jobs.lever.co/spotify",
        "palantir",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("pulsedata/lever-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 '{
  "startUrls": [
    "https://jobs.lever.co/spotify",
    "palantir"
  ]
}' |
apify call pulsedata/lever-jobs-scraper --silent --output-dataset

```

## MCP server setup

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