Lever Jobs Scraper & API
Pricing
Pay per usage
Lever Jobs Scraper & API
Free Lever jobs scraper: pay only for platform usage. Extract every open job from one or many Lever boards (US and EU) with titles, locations, teams, salary ranges, remote/hybrid/on-site type, descriptions, and publish dates. Filter by team, location, workplace type, keywords, or date.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Milad Amirzadeh
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
11 hours ago
Last modified
Categories
Share
Collect every open job from one or many Lever job boards in a single run: titles, locations, teams, departments, employment type, salary ranges, remote/hybrid/on-site type, full descriptions, and publish dates. Use the results for job-board feeds, recruiting research, salary benchmarking, hiring-trend tracking, and scheduled employer snapshots, with no login or API key.
The Actor is free to use: you pay only for Apify platform usage, which is typically a fraction of a cent per run.
Lever is the applicant tracking system behind the careers pages of companies such as Spotify, Palantir, Zoox, Shield AI, Veeva, and thousands more. This Actor reads Lever's public Postings API directly over HTTP. It runs without a browser or proxy and finishes most companies in a few seconds.
What you get
- All open jobs for one or many companies per run, from a slug (
spotify) or any board URL - Specific postings by URL (
job_detailsmode) - US and EU boards detected automatically (
jobs.lever.coandjobs.eu.lever.co) - Salary ranges with currency and period (year, month, hour), from Lever's salary fields and from the job description when the employer only writes the pay there (Spotify, Palantir, Veeva, and many others do). This roughly triples salary coverage.
- Workplace type (Remote, Hybrid, On-site) and country code, as set by the employer
- Team, department, commitment (employment type), and every listed location
- Company name, even though Lever's API does not provide one
- Full description as HTML, as clean plain text, and as structured bullet sections ("What you'll do", "Requirements")
- Filters for workplace type, department or team, location or country, commitment, keywords, publish date, and salary availability
- A per-company run summary showing open, matched, and saved counts, the detected region, and any slugs that were not found
Quick start
All jobs from several companies
{"mode": "company_jobs","companySlugs": ["spotify", "zoox", "https://jobs.eu.lever.co/seb"],"maxJobsPerCompany": 9999}
Filtered: recent remote or hybrid engineering roles mentioning Python
{"mode": "company_jobs","companySlugs": ["spotify", "zoox", "shieldai", "palantir"],"workplaceTypes": ["remote", "hybrid"],"filterDepartment": "Engineering","jobKeywords": ["python", "machine learning"],"postedAfter": "30 days","maxJobsPerCompany": 200}
Specific postings
{"mode": "job_details","jobUrls": ["https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1","https://jobs.eu.lever.co/seb/205c25b9-a4dc-41e2-8a23-7f3b2a887d21"]}
How to find a company's slug
Open the company's Lever board or any of its job postings. The slug is the path segment right after lever.co/:
| URL | Slug |
|---|---|
https://jobs.lever.co/spotify | spotify |
https://jobs.lever.co/zoox/2193db3f-... | zoox |
https://jobs.eu.lever.co/seb | seb |
You can paste any of these URLs directly. The Actor extracts the slug and finds the right region for you.
Input reference
| Field | Type | Default | Behavior |
|---|---|---|---|
mode | string | company_jobs | company_jobs lists all open jobs for each company. job_details fetches specific postings. |
companySlugs | array | ["spotify"] | Board slugs or URLs. Used in company_jobs mode. Duplicates are removed. |
jobUrls | array | [] | Lever posting URLs or slug/postingId. Used in job_details mode. |
includeContent | boolean | true | Save the description as HTML (content), plain text (descriptionText), and bullet sections. |
workplaceTypes | array | [] | Any of remote, hybrid, onsite, using the type the employer set in Lever. |
filterDepartment | string | empty | Case-insensitive partial match against the department or team. |
filterLocation | string | empty | Case-insensitive partial match against every listed location, such as London. A two-letter country code (DE, US, UK) matches the country only: DE does not match Denver, and CA means Canada. Remote also matches jobs whose workplace type is remote. A US state name such as California also finds its code ("San Francisco, CA"), and state codes that are not country codes (NY, TX) match the state. |
filterCommitment | string | empty | Case-insensitive partial match against the commitment, such as Full-time, Intern, or Contract. |
jobKeywords | array | [] | Up to 20 keywords or phrases. A job matches when any of them appears as a whole word in its title or description. |
postedAfter | string | empty | YYYY-MM-DD or relative (7 days). Inclusive, compared as UTC dates. |
onlyWithSalary | boolean | false | Keep only jobs with a salary, from Lever's salary fields or the description. |
maxJobsPerCompany | integer | 500 | Maximum jobs saved per company after filtering, newest first. Use 9999 for all. |
proxyConfiguration | object | off | Optional. The API is public, so a proxy is not required. |
All filters that you set must match (AND). Filters apply only in company_jobs mode.
Keyword matching uses whole words, so ML matches "ML Engineer" but not "HTML". Add every form you want to catch, such as engineer and engineering.
Output
Each saved job looks like this:
{"jobId": "e25fdd3f-628f-4141-b9fe-7298f3de55af","title": "Advisory Manager (Client Associate) in SOEs & Infrastructure team | SEB, Vilnius","companyName": "SEB","companySlug": "seb","location": "Vilnius","allLocations": ["Vilnius"],"country": "LT","workplaceType": "Hybrid","department": "Baltic","team": "Corporate Banking","commitment": "Corporate Banking","salaryMin": 3750,"salaryMax": 5650,"salaryCurrency": "EUR","salaryInterval": "month","salaryDescription": "(before tax deduction).\nThe final offer will depend on the experience and competencies of the selected candidate...","salarySource": "lever","url": "https://jobs.eu.lever.co/seb/e25fdd3f-628f-4141-b9fe-7298f3de55af","applyUrl": "https://jobs.eu.lever.co/seb/e25fdd3f-628f-4141-b9fe-7298f3de55af/apply","content": "<div><p><strong>Do you want your daily work to have a meaningful impact on Lithuania?</strong></p>...","descriptionText": "Do you want your daily work to have a meaningful impact on Lithuania?\nAt SEB, you do not just build a career...","sections": [{ "title": "What you will do", "items": ["Develop and strengthen relationships with Lithuania's largest public sector institutions...", "..."] }],"publishedAt": "2026-09-25T11:44:23+00:00","region": "eu","scrapedAt": "2026-09-26T20:57:42+00:00"}
| Field | Meaning |
|---|---|
jobId | Lever posting ID (UUID). |
title | Job title. |
companyName / companySlug | Company name read from the hosted posting page, and the board slug. The name falls back to the slug if the page is unavailable. |
location / allLocations | Primary location, and every location the posting lists. |
country | Two-letter country code set by the employer. |
workplaceType | Remote, Hybrid, On-site, or null when the employer left it unspecified. |
department / team / commitment | Lever's categories. Commitment is the employment type, named freely by each employer. |
salaryMin / salaryMax / salaryCurrency / salaryInterval | Salary range and its period (year, month, week, day, hour, one-time). A single figure has equal min and max. null when no salary is stated. |
salaryDescription | The employer's compensation note, or the sentence the salary was read from. |
salarySource | lever when the employer filled in Lever's salary fields, description when the salary was read from the job text, null when neither has one. |
url / applyUrl | Hosted job page and application page. |
content / descriptionText | Full description (intro, bullet lists, and closing text) as HTML and as plain text. null when includeContent is off. |
sections | The titled bullet lists as {title, items}, useful for extracting requirements or responsibilities. |
publishedAt | When the posting was created (UTC). |
region | Lever data region, us or eu. |
scrapedAt | When the job was collected (UTC). |
Results appear in the default dataset. Use the Job overview view for compact metadata, salaries, and links, or the Job descriptions view for text.
Run summary
Each run also writes an OUTPUT record to the default key-value store. It shows every target's status (ok, not_found, or error), its region, and its open, matched, and saved job counts, so you can spot mistyped slugs without reading the log. When no target succeeds, the run is marked as failed.
API and exports
Run the Actor from your application with the standard Apify API:
curl -X POST \"https://api.apify.com/v2/acts/miladamirzadeh~lever-jobs-scraper/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"companySlugs": ["spotify", "zoox"],"workplaceTypes": ["remote"],"maxJobsPerCompany": 50}'
You can also use the generated Python, JavaScript, CLI, OpenAPI, and MCP examples in the Actor's API tab. Datasets export to JSON, CSV, Excel, XML, and HTML.
Recurring workflows
Save a tested input as an Apify Task and schedule it daily or weekly. For daily runs, set postedAfter to 1 day so each run saves only postings published since the day before.
Typical uses:
- Job-board and aggregator ingestion
- Salary benchmarking across companies that publish pay ranges
- Tracking hiring volume by team, location, or workplace type
- Alerts for new roles at target companies, through Apify integrations such as Slack, Google Sheets, Make, or Zapier
Each run produces an independent dataset. The Actor does not keep history between runs.
Practical limitations
- You need each company's Lever slug. Lever has no public directory of all boards.
- Only published postings are available. Internal and unlisted postings are not exposed by the public API.
- Lever records when a posting was created, not when it was last edited, so there is no "updated after" filter.
- Salaries read from the description (
salarySource: "description") are the first salary the text states. When a posting lists several ranges (per city or level), the first one is saved andsalaryDescriptionshows its context. Amounts labeled OTE (on-target earnings), bonuses, and perks are skipped. - A bare
$is read as USD unless the text names another currency code, such asCAD. When the period isn't stated, it's inferred from the amount (for example, $18 is hourly and $120,000 yearly). - Commitment values are free text chosen by each employer, so the same employment type can be spelled differently across companies.
- Filters apply only in
company_jobsmode. - Closed postings return
not_foundinjob_detailsmode.
Pricing
The Actor is free. There is no per-run or per-result fee; you pay only for the Apify platform usage (compute units) of your runs, which the Apify free plan's monthly credit covers for most users.
Runs are cheap because the Actor makes plain HTTP requests with no browser or proxy. It runs at 512 MB by default and used under 180 MB in testing. Saving every job from Veeva and Palantir (about 1,200 jobs) took 23 seconds, which is well under 0.01 compute units.
Troubleshooting and support
If a run returns no jobs:
- Open the
OUTPUTrecord. Anot_foundstatus means the slug is wrong or the company does not use Lever. - Open the company's job posting in a browser and copy the slug from the URL.
- Remove the filters temporarily to rule out an overly narrow match.
For support, open an Actor issue with your input (without tokens), the run link, and what you expected to see.