Lever Jobs Scraper & API - Open Roles, Any Company
Pricing
from $1.20 / 1,000 jobs
Lever Jobs Scraper & API - Open Roles, Any Company
Track hiring across up to 200 Lever boards in one run, in one row shape you can diff daily. Zero open roles, a board that does not exist and a failed fetch are three different rows - never a silently empty result. Unofficial, not affiliated with Lever.
Pricing
from $1.20 / 1,000 jobs
Rating
0.0
(0)
Developer
NeverEmpty
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
8 hours ago
Last modified
Categories
Share
Pull every open job from any company's Lever job board, read straight from Lever's own public board API. No HTML scraping, no proxies, no API keys, nothing that breaks when a careers page is redesigned.
Unofficial. This Actor is not affiliated with, endorsed by, or sponsored by Lever. All product names are trademarks of their respective owners.
Don't know a company's board name? ATS Job Board Finder turns a domain into the board name this Actor takes.
It never returns an empty result to mean two different things
Most job-board Actors return an empty dataset when something goes wrong, and an empty dataset when there is genuinely nothing to report. Those are not the same answer, and if you are monitoring hiring activity the difference is the whole point.
Every board you ask for produces at least one row, tagged in the rowType column:
rowType | ok | What it means | Charged? |
|---|---|---|---|
job | true | A real open job | Yes |
no-open-roles | true | The board is live and has no open jobs (or none matching your filters) | No |
board-not-found | false | No board with that name exists on Lever | No |
unavailable | false | Lever could not be reached, or the entry could not be read as a board; reason says why | No |
budget-reached | false | The run hit the Max total charge you set. Names every board that was cut short and every board not fetched because of it | No |
You are charged only for job rows.
What Lever actually publishes - measured, not estimated
Run on 2026-09-01 with the shipped build and the default input: 155 job rows across 2 boards.
| spotify (88) | matchgroup (67) | |
|---|---|---|
title, jobUrl, postedAt, department | 100% | 100% |
employmentType | 97% | 96% |
workplaceType | 100% | 100% |
isRemote | 34% | 0% |
salaryMin / salaryMax | 0% | 0% |
isRemote is set only from Lever's own workplaceType, so it depends on how each company fills its board - 34% on one of the two default boards and 0% on the other. Lever publishes no structured salary, so salaryMin stays null everywhere. Lever returns createdAt as a UNIX millisecond number; here it is ISO 8601 UTC like every other source.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
boards | array | lever:spotify, lever:matchgroup | One entry per company board, up to 200 |
titleContains | string | (empty) | Keep only jobs whose title contains this text (case-insensitive) |
departmentContains | string | (empty) | Keep only jobs whose department or team contains this text |
locationContains | string | (empty) | Matches the primary location and every secondary location |
remoteOnly | boolean | false | Keep only jobs Lever itself flags as remote - never a guess |
postedWithinDays | integer | 0 (off) | Keep only jobs first published within N days. Unknown dates are excluded rather than assumed recent |
maxJobsPerBoard | integer | 0 (no limit) | Cap of job rows per board, applied after filtering |
includeDescription | boolean | false | Add the full description as plain text in descriptionText |
maxRetries | integer | 3 | Total attempts per board for temporary errors (HTTP 429 / 5xx). A 404 is a permanent answer and is not retried |
Naming a board: lever:spotify, or paste https://jobs.lever.co/spotify, or just spotify
Output columns
rowType, ok, reason, ats, companySlug, companyName, jobId, title, department, team, employmentType, locationRaw, locationsAll, country, city, workplaceType, isRemote, remoteHint, salaryMin, salaryMax, salaryCurrency, salaryInterval, salaryText, postedAt, updatedAt, jobUrl, applyUrl, descriptionText, source
All 29 columns are present on every row, in the same order - including the marker rows. The Greenhouse, Lever, Ashby, Workable and Workday Actors all return these same 29 columns, so adding another ATS never means rewriting your parser.
Two things it refuses to invent
isRemoteis set only when Lever itself says so. A guess based on the location text lives in a separate column calledremoteHint, so you always know which is which. A job located in "Remote, Oregon" is not a remote job.salaryMin/salaryMaxcome only from structured compensation fields. Nothing is parsed out of prose, and a missing figure staysnull- never0.
How it is checked
- 148 automated checks across 3 files, run before every publish
- 50 deliberate defects injected into the source; all 50 were caught by those checks (re-run and verified 2026-09-03)
- Only public job boards are read. Nothing needs a login, and no private ATS data is accessed
- Every request has a 45-second timeout, so a silent server cannot hang the run
- Up to 200 boards per run
The rest of the family
Same 29 columns, same row rules, one ATS each:
- greenhouse-jobs - Greenhouse boards
- ashby-jobs - Ashby boards
- workable-jobs - Workable boards
- workday-jobs - Workday boards
- ats-jobs-api - all five in one run, for a mixed list
- ats-board-finder - a company domain to the ATS and board name it uses
Support
Found a board that behaves oddly? Open an issue on the Issues tab and include the board name - it will be reproduced against the live API before anything is changed.