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

Scrape job postings from any Lever career site (jobs.lever.co): title, team, location, remote/hybrid, commitment, public salary range, dates, apply URL and full description. Filters, EU region, company discovery. From US$1.00 per 1,000 jobs.

- **URL**: https://apify.com/fabrikit/lever-jobs-scraper.md
- **Developed by:** [Fabrikit](https://apify.com/fabrikit) (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

from $1.00 / 1,000 job postings

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

Lever is the applicant tracking system behind thousands of career pages at `jobs.lever.co/<company>`. This Actor reads each company's public Lever postings feed and returns clean, uniform job records: title, team, department, locations, remote / hybrid / on-site, commitment, public salary range when the company shows one, publish date, apply URL and the full posting text.

Price: **US$1.00 per 1,000 jobs**, no subscription. Platform usage is included in the per-job price.

### What you can do

- Company slugs or any `jobs.lever.co` / `jobs.eu.lever.co` URL; a single posting URL scrapes just that job.
- Global and EU data regions (`api.lever.co` and `api.eu.lever.co`), automatic fallback.
- Filters: keywords, exclude keywords, locations, departments, teams, commitment, workplace type, remote only, posted within N days.
- Optional full description as plain text and HTML (`includeDescription`).
- Public salary range (min, max, currency, interval) when the posting has one.
- Company discovery: give company names or domains and the Actor tries to find their Lever board (best effort) and can scrape it right away.
- Direct requests to a public API: no browser, no login, very cheap to run.

### Input

| Field | What it does |
|---|---|
| `companies` | Lever companies: slug or URL (required) |
| `maxItems` | Total cap on jobs for the run (default 100) |
| `maxJobsPerCompany` | Optional per-company cap |
| `keywords` / `excludeKeywords` | Keep / drop jobs mentioning any of these words |
| `locations`, `departments`, `teams`, `employmentTypes` | Keep jobs containing any of these values |
| `workplaceTypes`, `remoteOnly` | Remote, hybrid or on-site |
| `postedWithinDays` | Only recent jobs |
| `includeDescription` | Add full description text and HTML |
| `proxyConfiguration` | Leave the default; used only if the source blocks |

Example:

```json
{
  "companies": [
    "spotify",
    "https://jobs.lever.co/palantir"
  ],
  "maxItems": 200,
  "keywords": [
    "engineer"
  ],
  "locations": [
    "Remote"
  ],
  "includeDescription": true
}
```

### Output

One dataset item per job. Lever shows a salary range only when the employer fills it in; those jobs have `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryInterval`.

| Field | Description |
|---|---|
| `platform`, `jobId` | Source platform and the posting's ID there |
| `title`, `company`, `companyName` | Job title; company slug as used in the URL; display name when the platform provides it |
| `location`, `locations`, `country` | Main location, all locations, country |
| `remote`, `workplaceType` | Remote flag and `remote` / `hybrid` / `onsite` when known |
| `department`, `team`, `employmentType` | Organisation and contract type |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryInterval`, `compensationSummary` | Public compensation when the platform exposes it, otherwise `null` |
| `postedAt`, `updatedAt` | ISO timestamps when known |
| `jobUrl`, `applyUrl` | Public posting and application links |
| `descriptionText`, `descriptionHtml` | Full description, only with `Include full description` |
| `scrapedAt` | When the record was produced |

Platform-specific extras are added after these fields (see the dataset schema).

Example item:

```json
{
  "platform": "lever",
  "jobId": "2193db3f-77c5-43b8-b030-8f92c9882bf1",
  "title": "Android Engineer - Experience",
  "company": "spotify",
  "companyName": null,
  "location": "London",
  "locations": [
    "London",
    "Stockholm"
  ],
  "country": "GB",
  "remote": false,
  "workplaceType": "hybrid",
  "department": "Engineering",
  "team": "Experience",
  "employmentType": "Permanent",
  "salaryMin": null,
  "salaryMax": null,
  "salaryCurrency": null,
  "salaryInterval": null,
  "compensationSummary": null,
  "postedAt": "2026-06-23T11:29:45.805Z",
  "updatedAt": null,
  "applyUrl": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1/apply",
  "jobUrl": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1",
  "descriptionText": "We design Spotify’s consumer experience—end to end, moment to moment, across every screen, platform, and partner integration. Our mission is to make listening f...",
  "descriptionHtml": "<div>\n<p>We design Spotify&rsquo;s consumer experience&mdash;end to end, moment to moment, across every screen, platform...",
  "region": "global",
  "scrapedAt": "2026-10-13T15:09:12.334Z"
}
```

A `SUMMARY` record in the key-value store lists, per company, how many postings were found, how many matched your filters, and why the run stopped.

### Pricing

| Event | Price |
|---|---|
| Job posting saved to the dataset (`job-result`) | US$0.001 (US$1.00 per 1,000) |

You only pay for jobs that match your filters and are saved. Set a maximum cost per run in the Apify console and the Actor stops cleanly when it is reached.

### Use cases

- Recruiting and sourcing: find open roles at target companies.
- Market and competitor intelligence: hiring trends by team and location.
- Lead generation: companies that are hiring for a role you sell to.
- Job aggregators and alerts: feed new postings into your own board or Slack.

### FAQ

**How does company discovery work?**
Put names or domains in `discoverCompanies` (for example `Palantir Technologies` or `spotify.com`). The Actor first looks for `jobs.lever.co/<slug>` links on the company's careers page, then tries likely slugs (`palantir`, `palantir-technologies`, ...) on the global and EU hosts. Boards it finds are added to the run; the full mapping, including names it could not resolve, is saved in the `DISCOVERY` record of the run's key-value store. Set `discoverOnly` to resolve slugs without scraping (nothing is charged). Discovery is best effort: a company that is not on Lever, or uses an unusual slug, will not be found.

**Does it work for EU-hosted boards?**
Yes. `Region` defaults to automatic (global host first, then EU). URLs on `jobs.eu.lever.co` go straight to the EU host.

**Do I need an account, API key or proxy?**
No. The data comes from public career pages and feeds. Requests go out directly; if a source ever blocks them the Actor climbs automatically to Apify datacenter and then residential proxies.

**What personal data is included?**
Only company and job data. Recruiter, hiring-manager and contact names are not collected, and emails, phone numbers and personal profile links are removed from descriptions.

**How many jobs can I get?**
Everything the company has published right now, up to `Max jobs`. Large boards with thousands of postings are fine.

**What happens if a company is not found?**
It is skipped with a warning and listed in the `SUMMARY` record. If none of your companies exist, the run fails with a clear message instead of finishing with an empty dataset.

**Is it legal?**
The Actor reads publicly accessible job listings that employers publish for candidates and does not log in or bypass any protection. You remain responsible for how you use the data and for complying with the platform's terms and applicable law (for example data-protection rules if you combine it with personal data).

### En espanol

Extrae ofertas de empleo de cualquier sitio de carreras en Lever (`jobs.lever.co`): titulo, equipo, ubicaciones, remoto/hibrido, tipo de contrato, rango salarial publico, fecha, enlace de postulacion y descripcion completa. Acepta slugs o URLs, regiones global y EU, filtros y un modo de descubrimiento de empresas por nombre o dominio. Precio: US$1,00 por 1.000 ofertas.

# Actor input Schema

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

Lever company slugs (`spotify`) or board URLs (`https://jobs.lever.co/palantir`, `https://jobs.eu.lever.co/<slug>`). A posting URL scrapes just that job. The slug is the last part of the company's jobs.lever.co address.

## `discoverCompanies` (type: `array`):

Optional, best effort: company names or website domains (e.g. `Palantir Technologies`, `spotify.com`). The Actor looks for their Lever job board (careers-page links first, then slug guesses on the global and EU hosts) and adds the boards it finds to the run. The mapping is saved in the `DISCOVERY` record of the key-value store.

## `discoverOnly` (type: `boolean`):

Only resolve the discover list and write the `DISCOVERY` record; do not scrape jobs (nothing is charged).

## `region` (type: `string`):

Lever stores customers in a global or an EU region. Auto tries global first and falls back to EU when the board is not found. URLs on jobs.eu.lever.co are always routed to the EU host.

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

Stop after this many jobs in total (all companies together).

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

Keep at most this many matching jobs per company. 0 = no limit.

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

Keep only jobs whose title, department, team, employment type or description contains ANY of these words (case and accent insensitive). Leave empty for all jobs.

## `excludeKeywords` (type: `array`):

Drop jobs that contain ANY of these words (same fields as Keywords).

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

Keep jobs whose location text contains ANY of these (e.g. `Berlin`, `Remote`, `United States`, `Santiago`).

## `departments` (type: `array`):

Keep jobs whose department contains ANY of these (e.g. `Engineering`, `Sales`).

## `teams` (type: `array`):

Keep jobs whose team contains ANY of these.

## `employmentTypes` (type: `array`):

Keep jobs whose employment type contains ANY of these (e.g. `Full-time`, `Intern`, `Contract`, `Permanent`).

## `workplaceTypes` (type: `array`):

Keep only these workplace models.

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

Keep only jobs flagged as remote.

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

Keep only jobs published in the last N days. 0 = any age.

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

Add `descriptionText` and `descriptionHtml` (full posting: intro, responsibilities, requirements, benefits). Makes the dataset larger. Emails, phone numbers and personal profile links are removed.

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

Requests go direct first (the source is a public API). If the source ever blocks them, the Actor climbs automatically to Apify datacenter and then residential proxies. Leave the default.

## Actor input object example

```json
{
  "companies": [
    "spotify"
  ],
  "discoverOnly": false,
  "region": "auto",
  "maxItems": 50,
  "maxJobsPerCompany": 0,
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All job postings collected during the run

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

Per-company counts, filters applied, proxy rung and stop reason

# 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"
    ],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/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"],
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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