# Lever Jobs Scraper (with Salaries) (`jamie_developer/lever-jobs-scraper`) Actor

All open jobs from any Lever job board (jobs.lever.co, EU): title, location, team, remote, published salary range, apply link, full description. Filters. No login or proxies.

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

## Pricing

from $1.50 / 1,000 job saveds

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 (with Salaries)

Download every open job from any company's **Lever** job board as clean JSON, CSV or Excel: title, location, department, workplace type, posting date, salary when stated, apply link and the full description. Add as many companies as you like, filter by title, location, remote, salary and posting date, and schedule it to get only new jobs every day.

> **Why this one**
>
> - **Clean, consistent fields:** the same names as for 7 other ATSs, ready for one table or database.
> - **Fast and cheap:** it reads Lever's public job board feed. No login, no browser, no proxies, and no breakage when the careers page design changes.
> - **Filtered-out and already-seen jobs are free.** You pay only for jobs you keep.

**Need other ATSs?** [ATS Jobs Scraper](https://apify.com/jamie_developer/ats-jobs-scraper) does the same for Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Personio, Recruitee and Workable in one run, and looks up a company by name.

### What to paste

- `spotify` (just the company name from the board URL)
- `https://jobs.lever.co/spotify`
- EU-hosted boards on `https://jobs.eu.lever.co/<company>` (detected automatically)

**How do I know a company uses Lever?** Click any job on the company's careers page. If the address starts with `jobs.lever.co/<name>`, the company uses Lever. You can also paste the careers page itself.

### Lever-specific details

- **Salaries:** most US Lever ads state the pay range in the ad text ("The estimated salary range for this position is $60,000 - $97,000/year"). The Actor extracts it into `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod`, keeps the original sentence in `salaryText`, and marks it `salarySource: description`. In a test on Palantir's board, 28 of 40 jobs had a range. Turn on *Jobs with salary only* to keep just those.
- Lever also gives you team, department, commitment (employment type), workplace type (remote/hybrid/on-site), all locations, country and creation date.
- The description combines Lever's intro, every list section (responsibilities, requirements, benefits) and the closing text into one readable text.

### Output fields

`title`, `company`, `location`, `locations`, `country`, `workplaceType` (remote / hybrid / onsite), `department`, `team`, `employmentType`, `postedAt`, `updatedAt`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryText`, `salarySource` (`ats` or `description`), `url`, `applyUrl`, `description` (plain text; HTML optional), `ats`, `companySlug`, `jobId`, `sourceUrl`, `scrapedAt`.

This Actor also reads other ATS boards when you paste their URL, so a mixed company list works in one run.

### Example input

```json
{
  "companies": [
    "spotify",
    "palantir"
  ],
  "titleKeywords": [
    "engineer"
  ],
  "locationKeywords": [
    "Germany",
    "Remote"
  ],
  "postedWithinDays": 14
}
```

### Schedules, job alerts and integrations

- **Only new jobs:** turn on *Only jobs not returned before* and schedule the Actor daily. The first run returns all current jobs; later runs return only jobs that weren't returned before, and the skipped ones aren't charged.
- **Send them anywhere:** Apify's built-in integrations push each run's jobs to Google Sheets, Slack, email, Make, Zapier, n8n or a webhook. A daily schedule plus *Only jobs not returned before* gives you a job alert feed.

### Use cases

- **Job boards and newsletters:** pull fresh jobs from a curated list of employers every day.
- **Recruiting and competitive intelligence:** see which roles and locations competitors are hiring for.
- **Sales prospecting:** hiring for a role is a buying signal for tools and services in that area.
- **Labor-market research:** compare titles, remote share and published salary ranges.

### Pricing

You pay per job saved. Jobs removed by your filters and jobs skipped as already seen are free. The price is on the Pricing tab. Set a maximum cost per run and the Actor stops cleanly when it's reached.

### FAQ

**Why did a company return 0 jobs?** The board has no open roles, or the company name is wrong. Open the board URL in your browser to check. The run's **SUMMARY** record (key-value store) lists every input with jobs checked, saved and any error.

**Is this allowed?** The Actor only reads the public job board feed that Lever provides so companies can publish their openings. It doesn't log in or collect candidate data. Job descriptions belong to the employers, so check your use (e.g. republishing) against their terms. This Actor is not affiliated with Lever.

**Something is missing or broken?** Open an issue on the Issues tab with the board URL.

# Actor input Schema

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

One per line. Paste Lever board URLs or just the company name, e.g. spotify, palantir. You can also paste a company's own careers page and the Actor finds the embedded job board.

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

Keep only jobs whose title contains at least one of these words (case-insensitive), e.g. engineer, sales, data. Leave empty to get all jobs.

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

Drop jobs whose title contains any of these words, e.g. intern, senior.

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

Keep only jobs whose location contains one of these words, e.g. Berlin, Germany, Remote, Zurich.

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

Keep only jobs marked as remote by the ATS (or with 'remote' in the location).

## `salaryOnly` (type: `boolean`):

Keep only jobs that state a pay range, either in the ATS's salary fields or written in the description.

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

Keep only jobs posted in the last N days. 0 = no date filter. Jobs without a posting date are kept.

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

For scheduled runs: return only jobs that earlier runs of the same search haven't returned yet. The first run returns all current jobs. Jobs already seen are skipped and not charged.

## `stateName` (type: `string`):

Name for the 'already seen' memory used by 'Only jobs not returned before'. Leave empty to derive it from the companies and filters; set it to keep the memory when you edit the company list.

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

Add the full job description as plain text. For Workday and SmartRecruiters this needs one extra request per job, so turn it off for faster runs.

## `includeDescriptionHtml` (type: `boolean`):

Add the original description HTML next to the plain text.

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

Stop after this many matching jobs per job board. 0 = no limit. Prefilled with 20 so a first try is quick and cheap; set 0 to get every job.

## `maxJobs` (type: `integer`):

Stop the whole run after this many jobs. 0 = no limit.

## Actor input object example

```json
{
  "companies": [
    "spotify",
    "palantir"
  ],
  "remoteOnly": false,
  "salaryOnly": false,
  "postedWithinDays": 0,
  "onlyNewJobs": false,
  "includeDescription": true,
  "includeDescriptionHtml": false,
  "maxJobsPerCompany": 20,
  "maxJobs": 0
}
```

# Actor output Schema

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

All saved jobs in one normalized format (title, company, location, salary, dates, links, description).

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

Per input: job board used, jobs checked, jobs saved and any error.

# 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"
    ],
    "maxJobsPerCompany": 20
};

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

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

```

## MCP server setup

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