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

Extract public Lever job boards through Lever's public postings API. Returns validated job postings with locations, teams, descriptions, compensation fields, timestamps, and application URLs for recruiting and job-market research.

- **URL**: https://apify.com/khadinakbar/lever-jobs-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Jobs, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 validated lever job returneds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Lever Jobs Scraper

Lever Jobs Scraper turns known public Lever boards into one structured record per current job opening. Recruiters, talent-intelligence teams, and job-market researchers can provide board tokens or board URLs and receive titles, locations, teams, employment types, public descriptions, compensation fields when available, timestamps, application URLs, and source provenance.

### Best fit for this Actor

- Use it when a company already exposes its openings on a public Lever board and you need an auditable dataset of its current roles.
- Start with a Lever board token such as `leverdemo-8`, or a public board-root URL such as `https://jobs.lever.co/leverdemo-8`.
- Use title, location, team, and employment-type filters before the actor writes billable job records.

Use it for defined public Lever boards, with one dataset record for each public posting. Company discovery, non-Lever career pages, application submission, and candidate records belong in separate workflows.

### Focused standalone workflow

This actor is designed as a focused standalone workflow for known public Lever boards. It works as a clear source-linked collection step before a team compares hiring activity, exports job data, or joins the records to an authorized employer-research workflow.

### Recruiting workflow: compare current engineering hiring

A talent researcher has a shortlist of employers using Lever. They provide the relevant board tokens and filter for remote engineering roles. Each returned record has a `title`, `location`, `team`, `commitment`, `postedAt`, `applyUrl`, and `sourceApiUrl`, making it straightforward to compare active hiring and retain a link back to the employer's public post.

### Quick start input

```json
{
  "boardTokens": ["leverdemo-8", "https://jobs.lever.co/leverdemo-8"],
  "maxResultsPerBoard": 100,
  "titleIncludes": "engineer",
  "locationIncludes": "remote",
  "teamIncludes": "engineering",
  "commitmentIncludes": "full-time",
  "includeDescriptions": true
}
```

`boardTokens` accepts raw public board tokens, public board-root URLs, and equivalent public Lever API URLs. Each supplied board has its own clear result boundary.

### Input reference

| Field | Type | What it controls |
| --- | --- | --- |
| `boardTokens` | array | One or more public Lever board tokens or board-root URLs. |
| `maxResultsPerBoard` | integer | Validated result boundary for each supplied board. |
| `titleIncludes` | string | Case-insensitive literal match against the public job title. |
| `locationIncludes` | string | Case-insensitive literal match against public location fields. |
| `teamIncludes` | string | Case-insensitive literal match against Lever's public team field. |
| `commitmentIncludes` | string | Case-insensitive literal match against Lever's public employment type. |
| `includeDescriptions` | boolean | Includes public description and supplementary HTML and clean text. |

### What data you receive

Each dataset item represents one public Lever job post. The public job and API source URLs, plus `scrapedAt`, preserve the source and observation time needed for current research.

| Field | Meaning |
| --- | --- |
| `jobId`, `boardToken`, `title` | Stable public identity for the job and its source board. |
| `location`, `allLocations`, `team`, `commitment` | Public role categorization for filtering and analysis. |
| `descriptionText`, `additionalText` | Clean public job detail when descriptions are requested. |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryInterval` | Public compensation fields when the board exposes them. |
| `applyUrl`, `jobUrl` | Public employer application and hosted-posting paths. |
| `postedAt`, `scrapedAt`, `sourceApiUrl` | Freshness and provenance fields. |

```json
{
  "jobId": "abc-123",
  "boardToken": "example",
  "title": "Senior Software Engineer",
  "location": "Remote",
  "allLocations": ["Remote", "New York, NY"],
  "team": "Engineering",
  "commitment": "Full-time",
  "workplaceType": "remote",
  "descriptionText": "Build reliable APIs.",
  "salaryMin": 120000,
  "salaryMax": 180000,
  "salaryCurrency": "USD",
  "salaryInterval": "yearly",
  "applyUrl": "https://jobs.lever.co/example/abc-123/apply",
  "jobUrl": "https://jobs.lever.co/example/abc-123",
  "postedAt": "ISO 8601 timestamp when provided",
  "sourceApiUrl": "https://api.lever.co/v0/postings/example?mode=json",
  "scrapedAt": "ISO 8601 collection timestamp"
}
```

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~lever-jobs-scraper/runs?token=$APIFY_TOKEN" \
  -H "content-type: application/json" \
  -d '{"boardTokens":["leverdemo-8"],"maxResultsPerBoard":25}'
```

After collection completes, read the default dataset for job records. `OUTPUT` reports the compact terminal outcome, while `RUN_SUMMARY` records board coverage, diagnostics, and charged event counts.

### Use with AI agents through Apify MCP

> Collect up to 25 current public engineering roles from the Lever board `leverdemo-8`. Return each title, location, team, employment type, application URL, posted timestamp, and source URL. Read the dataset and terminal outcome, preserve the source URLs, and stay within the requested result boundary and cost scope.

The actor is read-only. An agent can recognize `VALID_EMPTY` as a successful no-match result, preserve `sourceApiUrl` and `jobUrl`, and use `RUN_SUMMARY` to report board diagnostics alongside the dataset.

### Pricing

This actor uses Pay per event plus Apify platform usage. Each validated public job record written to the dataset is billed at **$0.003**; the actor-start event is **$0.00005** per GB of configured memory. Filters run before dataset writes, and the actor logs the maximum possible job-event cost for the supplied board and result limits. Open the live Pricing tab for current details; platform compute and network usage are additional.

### Best results

- Provide known, public Lever board tokens so the workflow starts with a defined employer set.
- Use a bounded result count and the literal filters to keep the collection focused on a recruiting question.
- Schedule repeat runs for monitoring, then compare `postedAt` with `scrapedAt` to distinguish source timing from collection timing.
- Preserve `sourceApiUrl` and `jobUrl` when sharing results so collaborators can review the source posting.

### Builder's note

I designed the output around Lever's stable `boardToken` because public boards can vary in their company-display metadata. That choice keeps source identity explicit, preserves a clean record shape, and lets the outcome contract communicate whether a board returned matching roles.

### Responsible use

Use public or authorized data in line with applicable laws, the target site's terms, and your organization's data-handling practices. The collection focuses on public job postings and keeps application interaction and candidate records outside its scope.

# Actor input Schema

## `boardTokens` (type: `array`):

Use this when you know a company's public Lever board, for example lever or https://jobs.lever.co/lever. Enter up to 25 unique board tokens or root public board URLs. This field is required. It is not a company website, an individual job URL, a login page, or an application form.

## `maxResultsPerBoard` (type: `integer`):

Use this to cap validated jobs returned from each supplied Lever board. Enter an integer such as 100. It defaults to 100 and accepts 1 through 1,000. This is a per-board result cap, not a page count or a global charge budget.

## `titleIncludes` (type: `string`):

Use this when you need jobs whose public title contains literal text, for example engineer. Matching is case-insensitive. Leave it blank to retain every public title. This is not Boolean search and does not search the description.

## `locationIncludes` (type: `string`):

Use this when you need jobs whose public Lever location contains literal text, for example remote or london. Matching is case-insensitive across the primary and alternate public locations. Leave it blank to retain every location. This does not geocode a job or infer location from its description.

## `teamIncludes` (type: `string`):

Use this when you need a public Lever team containing literal text, for example engineering. Matching is case-insensitive against Lever's public team category. Leave it blank to retain every team. This does not infer a team from title words or job description text.

## `commitmentIncludes` (type: `string`):

Use this when you need a public Lever commitment such as full-time, contract, or internship. Matching is case-insensitive against the board's commitment field. Leave it blank to retain every employment type. This is not a date filter or a candidate availability filter.

## `includeDescriptions` (type: `boolean`):

Use this to include the public Lever description and additional text in HTML and clean-text fields. Set true for detailed recruiting and research output or false for a smaller result. It defaults to true. This does not retrieve private hiring notes, candidate data, or application responses.

## Actor input object example

```json
{
  "boardTokens": [
    "leverdemo-8",
    "https://jobs.lever.co/leverdemo-8"
  ],
  "maxResultsPerBoard": 100,
  "titleIncludes": "engineer",
  "locationIncludes": "remote",
  "teamIncludes": "engineering",
  "commitmentIncludes": "full-time",
  "includeDescriptions": true
}
```

# Actor output Schema

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

Validated public Lever job records returned by this run.

## `output` (type: `string`):

Compact outcome, item counts, warnings, and charged event totals.

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

Detailed board coverage, diagnostics, and billing information for this run.

# 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 = {
    "boardTokens": [
        "leverdemo-8"
    ],
    "maxResultsPerBoard": 100,
    "titleIncludes": "",
    "locationIncludes": "",
    "teamIncludes": "",
    "commitmentIncludes": "",
    "includeDescriptions": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/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 = {
    "boardTokens": ["leverdemo-8"],
    "maxResultsPerBoard": 100,
    "titleIncludes": "",
    "locationIncludes": "",
    "teamIncludes": "",
    "commitmentIncludes": "",
    "includeDescriptions": True,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/lever-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "boardTokens": [
    "leverdemo-8"
  ],
  "maxResultsPerBoard": 100,
  "titleIncludes": "",
  "locationIncludes": "",
  "teamIncludes": "",
  "commitmentIncludes": "",
  "includeDescriptions": true
}' |
apify call khadinakbar/lever-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/lever-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/zThhdw9tYfPAM6GEz/builds/gcwm22X2pQ7iwBi3n/openapi.json
