# Lever Jobs Scraper & API (+ Greenhouse, Ashby, Workable) (`wintersworks/lever-jobs-scraper`) Actor

Lever jobs from any company's jobs.lever.co board (US and EU), plus Greenhouse, Ashby and Workable. Normalized listings with location, workplace type, team, salary range and apply link. $1.50 per 1,000 jobs.

- **URL**: https://apify.com/wintersworks/lever-jobs-scraper.md
- **Developed by:** [Winters Works](https://apify.com/wintersworks) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 job 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

## Lever Jobs Scraper & API (+ Greenhouse, Ashby, Workable)

**Lever jobs as clean JSON or CSV: $1.50 per 1,000 jobs.** The Apify Free plan's $5 monthly credit covers about 3,000 jobs.

Point it at any company that hires through Lever (the careers pages at `jobs.lever.co/<company>`) and get every open role as a flat record: title, team, department, location, workplace type, commitment, salary range when the company publishes one, posting date and the apply link. EU-hosted boards (`jobs.eu.lever.co`) work too, with no extra setting.

It reads Lever's public postings API, the same feed Lever provides for companies to embed their careers pages. No login, no browser, no proxies, so runs take seconds and cost very little.

### Who uses Lever job data

- **Recruiters and sourcers:** watch a list of Lever companies for new roles in one team or city.
- **Sales teams:** a company hiring three data engineers is about to buy data tools. Use new postings as a buying signal.
- **Job boards and newsletters:** a direct-from-employer feed with the same fields for every company.
- **Job seekers:** schedule a daily run on your target companies and get only the new postings.
- **Analysts:** remote share, pay ranges and hiring pace by company.

### Input

| Field | What it does |
|---|---|
| `companies` | Lever URLs (`https://jobs.lever.co/spotify`) or bare slugs (`spotify`). Default: `spotify`, `palantir`, `zoox` |
| `keyword` | All of these words must appear in the title, team, department or description |
| `location` | The location must contain this text, e.g. `London` |
| `remoteOnly` | Only roles Lever marks as remote (or whose location says remote) |
| `department` | Department or team must contain this text, e.g. `Engineering` |
| `postedWithinDays` | Only roles posted in the last N days |
| `includeDescription` | Add the full description as plain text (`descriptionText`) |
| `maxResults` / `maxPerCompany` | Caps, newest first. 0 = no cap |
| `onlyNew` | Only roles not returned by earlier runs |
| `stateStoreName` | Named store that remembers which roles you've seen |

**Finding a slug:** open the company's careers page and click a job. If the URL starts with `jobs.lever.co/palantir/...`, the slug is `palantir`. You can also paste the careers URL as is.

**Bare slugs** are checked on Lever first. If the company isn't on Lever, the Actor tries Greenhouse, Ashby, Workable and SmartRecruiters, so a mixed watchlist works in one run. To pin a company to one system, write `greenhouse:stripe` or `lever:spotify`.

Example: remote engineering roles posted this week at three Lever companies.

```json
{
  "companies": ["https://jobs.lever.co/spotify", "palantir", "zoox"],
  "department": "Engineering",
  "remoteOnly": true,
  "postedWithinDays": 7,
  "maxPerCompany": 0,
  "maxResults": 0
}
```

### Output

When a cap cuts results short, the last row is a free `recordType: "runNotice"` row explaining what was cut. Filter it out by `recordType` if you don't want it.

One record per job. A Lever example:

```json
{
  "ats": "lever",
  "company": "spotify",
  "jobId": "ddc10181-6ecc-4dfc-9d02-2c5ce820cfdd",
  "title": "Senior Product Manager, Consumer - Audiobooks",
  "department": "Product",
  "team": "Audio Books & Gated Content",
  "location": "London; Stockholm",
  "remote": false,
  "employmentType": "Permanent",
  "compensation": null,
  "compensationMin": null,
  "compensationMax": null,
  "compensationCurrency": null,
  "compensationInterval": null,
  "postedAt": "2026-10-12T13:42:44.230Z",
  "updatedAt": null,
  "applyUrl": "https://jobs.lever.co/spotify/ddc10181-6ecc-4dfc-9d02-2c5ce820cfdd/apply",
  "scrapedAt": "2026-10-13T14:47:53.275Z"
}
```

`employmentType` is Lever's commitment field (Full-time, Permanent, Intern and so on). Salary fields are filled only when the company publishes a range on Lever; otherwise they are `null`. `updatedAt` isn't provided by Lever. Download the dataset as JSON, CSV, Excel or HTML, or read it through the Apify API.

### Get only new Lever jobs every day

1. Set `onlyNew` to `true` and give the watchlist a `stateStoreName`, e.g. `fintech-lever-watch`.
2. Add an Apify Schedule (daily or hourly).
3. Send results on with a webhook, an email notification, or the Zapier, Make, n8n, Slack or Google Sheets integrations.

The first run returns everything that matches and remembers the job IDs. Each later run returns, and charges for, only roles that weren't there before. Use a separate `stateStoreName` for each watchlist.

### Pricing

| Event | Price | Per 1,000 |
|---|---|---|
| `job-result` (one job returned) | $0.0015 | $1.50 |

1,000 jobs = $1.50, 10,000 jobs = $15. Filters run before charging, so you pay only for jobs in the dataset. A company that isn't found or has no open roles costs nothing, and the run's status message says which inputs came back short and why. You can set a maximum cost per run in the run options.

### Use it from code or an AI agent

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("wintersworks/lever-jobs-scraper").call(run_input={
    "companies": ["spotify", "palantir"],
    "keyword": "data",
    "postedWithinDays": 7,
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(job["company"], job["title"], job["applyUrl"])
```

AI assistants (Claude, Cursor and other MCP clients) can call it through Apify's hosted MCP server at `https://mcp.apify.com?actors=wintersworks/lever-jobs-scraper`, with your Apify token as a Bearer header. Then ask, for example: "Which of spotify, palantir and zoox posted engineering jobs on Lever this week? Give me the apply links."

### FAQ

**Is this allowed?** It reads only the public postings endpoint Lever offers for embedding careers pages. It doesn't log in or get around anything, and the postings are published by the employers. You're responsible for how you use the data, including privacy and marketing laws. Not affiliated with or endorsed by Lever.

**A company returned nothing.** Its Lever slug may differ from its name (check the careers URL), it may use another applicant tracking system such as Workday or iCIMS, which aren't supported, or it may have no open roles right now.

**Can I get every job on Lever?** No. Lever has no public directory of companies, so you supply the list.

**Do I need proxies?** No. The API is public and fast; a run over a handful of companies finishes in seconds.

### More from Winters Works

- [Greenhouse Jobs Scraper & API](https://apify.com/wintersworks/ats-job-board-feeds): the same normalized output, built around Greenhouse boards, with Lever, Ashby, Workable and SmartRecruiters too.
- [Bulk Email Verifier & MX Record Checker](https://apify.com/wintersworks/bulk-email-verifier-dns): syntax, MX, disposable and role-address checks, no SMTP probing.
- [Website Tech Stack & SEO Audit](https://apify.com/wintersworks/website-tech-stack-seo-audit): what a list of sites runs on, plus SEO basics and a 0-100 score.
- [WHOIS & Domain Availability MCP Server](https://apify.com/wintersworks/domain-whois-mcp-server): give your AI agent domain lookups, expiry dates and availability checks over RDAP.

Built and maintained by Winters Works. Questions or requests: open an issue on the Actor page or email wintersworks.shop@gmail.com.

# Actor input Schema

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

Lever careers URLs (jobs.lever.co/spotify, jobs.eu.lever.co/<company>) or bare company slugs. A bare slug is checked on Lever first, then Greenhouse, Ashby, Workable and SmartRecruiters. Prefix to force one ATS, e.g. greenhouse:stripe.

## `keyword` (type: `string`):

Only jobs whose title, department, team or description contain ALL of these words (case-insensitive). Example: data engineer

## `location` (type: `string`):

Only jobs whose location contains this text (case-insensitive). Example: London, Germany, New York

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

Only return jobs flagged or described as remote.

## `department` (type: `string`):

Only jobs whose department or team contains this text. Example: Engineering

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

Only jobs first posted in the last N days. 0 = no limit.

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

Add the job description converted from HTML to plain text. (SmartRecruiters needs one extra request per job.)

## `maxResults` (type: `integer`):

Stop after this many jobs across all companies. 0 = no cap.

## `maxPerCompany` (type: `integer`):

Cap per company (newest first). 0 = no cap.

## `onlyNew` (type: `boolean`):

Return only jobs not seen in previous runs. Seen job IDs are kept in a named key-value store, so scheduled runs yield just new postings. The first run returns everything.

## `stateStoreName` (type: `string`):

Named key-value store used by 'Only new jobs'. Use different names for different monitors.

## Actor input object example

```json
{
  "companies": [
    "spotify",
    "palantir",
    "zoox"
  ],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": false,
  "maxResults": 6,
  "maxPerCompany": 2,
  "onlyNew": false,
  "stateStoreName": "lever-jobs-seen"
}
```

# Actor output Schema

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

All result items from the run's default dataset.

# 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": [
        "spotify",
        "palantir",
        "zoox"
    ],
    "maxResults": 6,
    "maxPerCompany": 2
};

// Run the Actor and wait for it to finish
const run = await client.actor("wintersworks/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 = {
    "companies": [
        "spotify",
        "palantir",
        "zoox",
    ],
    "maxResults": 6,
    "maxPerCompany": 2,
}

# Run the Actor and wait for it to finish
run = client.actor("wintersworks/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 '{
  "companies": [
    "spotify",
    "palantir",
    "zoox"
  ],
  "maxResults": 6,
  "maxPerCompany": 2
}' |
apify call wintersworks/lever-jobs-scraper --silent --output-dataset

```

## MCP server setup

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