# Lever Jobs Scraper (`lergassy/lever-jobs-scraper`) Actor

\[$1.20/1K jobs] Scrape every open job from any company's Lever board: title, team, all locations, country, remote / hybrid / on-site, commitment, salary when posted, date, full description, apply link. Filters, no login.

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

## Pricing

from $0.84 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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** downloads every open job from the Lever job boards of the companies you list. Give it company slugs (`spotify`) or careers URLs (`https://jobs.lever.co/palantir`), press Start, and get one row per job: title, department, location, remote / hybrid / on-site, salary when the company publishes it, publish date, the full description, the job and apply links, and any recruiter emails written in the posting. Filter by title keywords, location, workplace and date. No login, no API key, no browser. Export JSON, CSV or Excel, schedule it, or call it from the API.

> This Actor is a focused entry point for the query "lever jobs". It runs the same engine as **[Jobs API — Indeed, LinkedIn & career sites](https://apify.com/lergassy/jobs-api)**, which also reads Greenhouse, Lever, Ashby, Workable and SmartRecruiters boards and searches Indeed and LinkedIn. Use Jobs API when you need several systems or job boards in one run.

### What does the Lever jobs scraper do?

Lever is the applicant-tracking system behind the careers pages of thousands of companies. Every company on Lever has a public job board (`jobs.lever.co/<slug>`), and Lever serves that board through a public JSON API (api.lever.co). This Actor reads that API for each company in your list — one request returns the whole board, with descriptions — and turns it into clean rows in the same format for every company.

- **Whole boards in seconds.** A company with 800 open roles is one request, not 800 page visits.
- **Filters applied for you:** title keywords, locations, remote / hybrid / on-site, posted within a day / week / month or after a fixed date. Jobs come newest first, so a per-company cap keeps the freshest ones.
- **Normalised fields** you can sort and join: ISO dates, `isRemote` and `workplaceType`, `salaryMin` / `salaryMax` as numbers.
- **Nothing silently disappears.** A company slug that does not exist on Lever gets its own free error row saying so; a run where the filters left nothing gets a free row explaining which filter to widen.

**What it does not do:** it does not search *all* Lever companies at once — you give the companies. There is no global directory of Lever boards in this Actor. If you need a keyword search across the whole job market, use [Jobs API](https://apify.com/lergassy/jobs-api) (Indeed + LinkedIn).

### What data does it return?

| Field | Example |
|---|---|
| `source`, `board`, `id`, `url`, `applyUrl` | lever · spotify · 186b763a-… · https://jobs.lever.co/spotify/186b763a-… · …/apply |
| `title`, `company`, `department` | Backend Engineer II - Data Platform · spotify · Platform |
| `location`, `allLocations`, `countryCode` | Stockholm · \["Stockholm", "London"] · SE |
| `workplaceType`, `isRemote` | hybrid · false (Lever's own field: remote / hybrid / onsite) |
| `employmentType`, `jobTypes` | permanent · \["permanent"] (Lever's "commitment", as the company wrote it: full-time, contract, intern…) |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | when the company publishes a salary range on Lever, else null |
| `postedAt` | 2026-09-28T10:19:51.162Z (posting created) |
| `description`, `descriptionHtml` | full text and HTML, including the requirement lists |
| `emails`, `phones`, `companyDomain` | addresses written in the posting · domain from the apply link when it is the company's own site |
| `query`, `scrapedAt` | (empty for boards) · run time |

- **Workplace** is Lever's own field. Jobs where the company left it "unspecified" have `workplaceType: null` and count as remote only if the location says "Remote".
- **Company** is the board slug (`spotify`), because Lever's public API does not return the company's display name.
- **Salary** is filled only when the company enters a salary range in Lever; many do not.

### How much does it cost?

**$1.20 per 1,000 jobs** ($0.0012 per job row) on the Free plan, down to $0.84 per 1,000 on higher Apify plans. No fee per run, per company or per request. Error rows (unknown company, a board that did not answer) and the "nothing matched" explanation row are free. Jobs removed by your filters are not charged — you pay only for rows in the dataset.

Example: 10 companies × 150 open jobs = 1,500 rows = $1.80 on the Free plan. Filter to "engineer" + "remote" and you pay only for those rows.

### How to scrape Lever jobs

1. Open the **Input** tab.
2. Put company slugs or careers URLs into **🏢 Companies on Lever**, one per line. The slug is the part after the board domain: in `https://jobs.lever.co/palantir` it is `palantir`.
3. Optional: add **Title keywords**, **Locations**, **Workplace** and **Posted within**.
4. Press **Start**, then download the results from the **Output** tab, or read them through the API.

An empty API call works too: with no companies, the Actor returns a demo — the 20 newest jobs each from spotify, palantir and outreach.

### ⬇️ Input

```json
{
    "companies": ["spotify", "https://jobs.lever.co/palantir"],
    "locations": ["London", "Stockholm"],
    "workplace": "hybrid",
    "maxJobsPerCompany": 100
}
```

| Field | Default | What it does |
|---|---|---|
| `companies` | demo | Lever board slugs or careers URLs. A URL from another supported system (Greenhouse, Lever, Ashby, Workable, SmartRecruiters) also works |
| `titleKeywords` | empty | Keep jobs whose title or department contains one of the words |
| `locations` | empty | Keep jobs whose location contains one of the texts |
| `workplace` | `any` | `remote`, `hybrid` or `onsite` |
| `postedWithin` / `postedAfter` | any | Drop older jobs (`day`, `3days`, `week`, `month`, or a `YYYY-MM-DD` date) |
| `maxJobsPerCompany` | all | Cap per board after the filters, newest first |
| `maxItems` | 100,000 | Cap for the whole run |
| `includeDescription` | `true` | Full description text and HTML |
| `includeContacts` | `true` | Emails and phones found in the posting, free |
| `concurrency`, `proxyConfiguration` | 5, off | Boards read at once; no proxy needed — if a board refuses a direct request it is retried once through Apify Proxy |

### ⬆️ Output

One row per job with `"type": "job"`. Free rows with `"type": "error"` explain a company that could not be read or a search that matched nothing. Download as JSON, CSV, Excel or XML, or get it from the API (`/datasets/{id}/items`). A JSON summary of the run is saved as `STATS` in the key-value store.

### Use cases

- **Job boards and aggregators**: pull the full, current list of roles from the companies you track, every day.
- **Recruiting and sourcing**: watch competitors' and target companies' openings by department and location.
- **Sales and lead generation**: a company hiring five sales engineers is a company buying sales tools — filter by title and push to your CRM.
- **Market and salary research**: compare published salary ranges by role, location and company.
- **Job alerts**: schedule a daily run with `postedWithin: "day"` and send new postings to Slack, email or a Google Sheet.

### Tips

- Many companies use different systems for different brands. If a slug returns "not found", open the company's careers page and look at the job links: `greenhouse.io`, `lever.co` and `ashbyhq.com` tell you which system and slug to use.
- For a daily feed use **Schedules** with `postedWithin: "day"` (or `postedAfter` set to yesterday) so you pay only for new jobs.
- Everything in this Actor is available from the API and to AI agents through the Apify MCP server.

### ❓ FAQ

**Is it legal?** It reads job postings that companies publish publicly on purpose, through the public API Lever provides for job boards. Check your own use against the laws that apply to you, especially if you process personal data such as recruiter emails.

**Why is a company missing jobs I see on its website?** Some companies list a part of their roles on another system or hide internal postings from the public board. This Actor returns exactly what the public Lever board shows.

**Can I search all Lever companies by keyword?** Not with this Actor — you give the companies. For a market-wide keyword search use [Jobs API](https://apify.com/lergassy/jobs-api).

### Your feedback

Found a bug or a board that does not parse well? Open an issue on the **Issues** tab — we fix reports quickly.

# Actor input Schema

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

One company per line: its Lever board slug (<code>spotify</code>) or the careers URL (<code>https://jobs.lever.co/palantir</code>). The slug is the part after the board domain in the company's Lever job-board URL. Every open job on each board is returned (newest first), then the filters below are applied. Empty = a demo with spotify, palantir, outreach (20 jobs each).

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

Keep only jobs whose title or department contains one of these words (case-insensitive): <code>engineer</code>, <code>sales</code>, <code>product manager</code>. Empty = all jobs.

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

Keep only jobs whose location contains one of these texts (case-insensitive): <code>London</code>, <code>United States</code>, <code>Remote</code>, <code>Germany</code>. Matched against the location as the company wrote it plus the country code and every listed location. Empty = any location.

## `workplace` (type: `string`):

Uses Lever's own workplace field (remote / hybrid / on-site); jobs where the company left it unspecified count as remote only if the location says "Remote".

## `postedWithin` (type: `string`):

Drop jobs first published earlier than this. Lever gives the date the posting was created.

## `postedAfter` (type: `string`):

<code>YYYY-MM-DD</code>. Use instead of "Posted within" for a fixed date (handy for daily schedules).

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

Cap per board after the filters, newest first. Leave empty for every matching job (big boards have 500–900 open roles); the form starts at 20 so a first try stays cheap.

## `maxItems` (type: `integer`):

Stop after this many job rows in total.

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

Description as plain text and HTML. Turn off for a lighter export with titles, locations and links only.

## `includeContacts` (type: `boolean`):

Recruiter emails and phone numbers written in the job description, plus the company domain from the apply link. Free.

## `concurrency` (type: `integer`):

How many boards are read at once.

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

Not needed: Lever's public job-board API answers direct requests. If a board ever refuses, that one request is retried through Apify Proxy automatically.

## Actor input object example

```json
{
  "companies": [
    "spotify",
    "palantir",
    "outreach"
  ],
  "workplace": "any",
  "postedWithin": "any",
  "maxJobsPerCompany": 20,
  "maxItems": 100000,
  "includeDescription": true,
  "includeContacts": true,
  "concurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `rows` (type: `string`):

One row per job: source, title, company, company website and size, location, remote/hybrid, job type, salary as numbers, posting date, description, apply link, skills, emails and phones found in the posting.

## `runSummary` (type: `string`):

JSON counters for the run: rows delivered, filtered out, errors and request statistics.

# 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",
        "outreach"
    ],
    "maxJobsPerCompany": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("lergassy/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",
        "outreach",
    ],
    "maxJobsPerCompany": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("lergassy/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",
    "outreach"
  ],
  "maxJobsPerCompany": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call lergassy/lever-jobs-scraper --silent --output-dataset

```

## MCP server setup

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