Lever Jobs Scraper: jobs.lever.co Postings Export
Pricing
from $0.32 / 1,000 unique job results
Lever Jobs Scraper: jobs.lever.co Postings Export
Collect current jobs from public Lever.co boards (jobs.lever.co, global and EU) to track hiring at target companies, find leads by open roles or feed a job board. Official Lever postings API, no API key, login or proxy.
Pricing
from $0.32 / 1,000 unique job results
Rating
0.0
(0)
Developer
Cliqto Media
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
15 days ago
Last modified
Categories
Features
Share
Collect current job postings from public Lever.co boards (jobs.lever.co, global and EU) to track hiring at target companies, find sales leads by open roles, or feed your own job board. Add a board slug, board URL, or one exact job URL. It uses the official Lever postings API: no API key, login or proxy. Get one row per unique job with a stable ID, description and published salary.
Start with targets: ["leverdemo"]. The new Input form has this small example filled in. Pricing is $0.002 per start + $0.45 per 1,000 useful job rows on the Free plan (down to $0.315 on Gold) at the default 512 MB memory. Check RUN_SUMMARY when a board is empty, a filter removes jobs, or a source request fails.

Table of contents
- What it does
- How it works
- Quick start
- Use cases
- Input
- Output
- Pricing
- Limits
- API, export and integrations
- Troubleshooting
- FAQ
- Related Actors
- Support
What it does
Read public published postings from known Lever boards. Global and EU boards are supported. A bare slug uses the global service. An exact posting URL reads that job. The Actor uses the public Lever Postings API with direct HTTPS requests. No Lever account or API key is needed.
Get titles, locations, departments, teams, commitments, workplace types and public links. Keep HTML and plain descriptions, list sections and published salary fields when includeContent is true. The Actor gives each job a stable ID and records outcomes for all input targets.
Good fit
- A snapshot of open jobs on known company Lever boards.
- Recruiting market research by team, location, commitment or workplace type.
- A job feed built from exported rows with stable IDs.
- A scheduled job alert: with
onlyNewSinceLastRuneach run returns only jobs that earlier runs have not returned.
This product does not discover companies, search all Lever jobs, read private/internal or closed postings, submit applications, or report closed or changed jobs. Other ATS platforms need a separate Actor.
How it works
- You give public Lever board slugs, board URLs or exact job URLs. Each one is checked and normalized; duplicates are read once.
- The Actor reads the published jobs of each board from Lever's public postings service, global or EU, without a login, browser or proxy. Your filters and row caps are applied.
- It saves one Dataset row per unique job with a stable ID, and a
RUN_SUMMARYreport with a status for every target: jobs found, empty board, filtered out, not found or a technical error.
Quick start
-
Open the Input tab. Keep the filled
targetsexample,leverdemo, or paste your public Lever board URL such ashttps://jobs.lever.co/leverdemo(box 1 in the picture). Click + Add for more companies in one run. -
Keep Include descriptions and lists on for the full job text, lists and salary (box 2). Turn it off when titles, locations and links are enough.
-
Keep Maximum total jobs at the runtime default
5000or set100for a first test (box 3). Filters are optional, see Input. -
Optional: turn on Only new jobs since the last run for a scheduled job alert (box 4).
-
Click Start.
-
Open the Output tab (box 1 below). Each row is one job; check
title,location,departmentandcreatedAt(box 2). Open Storage → Key-value store → RUN_SUMMARY for each target's status and counts.
Expected result: one Dataset row per published job with a stable id; the demo board had 10 published jobs when checked on 27 October 2026. Live jobs may change. API calls must supply targets; an empty API input does not select the demo.
Use cases
| Task | Input | Useful fields | Next step |
|---|---|---|---|
| Monitor hiring at target companies | Their Lever board slugs in targets, onlyNewSinceLastRun: true, run on a schedule | sourceJobId, title, team, createdAt, observedAt | Each run gives only new jobs; for closed jobs, compare id values of two full runs without onlyNewSinceLastRun |
| Find sales leads from open roles | Boards of prospect companies, filters.teams such as Sales or Engineering | title, department, team, locations, hostedUrl | Push rows to your CRM or sheet |
| Feed a job board or job alert | includeContent: true, filters.locationIncludes, filters.descriptionIncludes or filters.postedWithinDays | descriptionText, salaryRange, workplaceType, applyUrl | Publish or send the rows from your own system |
| Recruiting market research | Many boards, filters by team, location or commitment | team, department, commitment, country, salaryRange | Group rows by team, place or pay |
| Recheck a known posting | Exact job URL in targets | Stable id, observedAt, source fields | See whether the job is still published |
Input
targets is required. It must have 1–50 strings. Duplicate normalized targets are fetched once. Invalid targets get INVALID_INPUT entries and are not fetched. A missing/empty target array or invalid option shape fails validation.
Fields
| Field | Type | Required | Runtime default / UI prefill | Allowed values and effect |
|---|---|---|---|---|
targets | array | yes | No runtime default. UI prefill and schema default: ["leverdemo"]. | Use a board slug such as leverdemo, a public Lever board URL, or one exact public job URL. Bare slugs use the global Lever service. |
includeContent | boolean | no | Runtime default: true. No UI prefill. | Keep the public HTML/plain job content and list sections in each result. |
filters | object | no | No filters. No UI prefill. | All filled filter groups must match. Values within one group use OR logic. |
maxJobsPerTarget | integer | no | Runtime default: 0. No UI prefill. | Stop each board after this many useful results. Use 0 for no per-board cap. Range 0–5000. |
maxTotalJobs | integer | no | Runtime default: 5000. No UI prefill. | Maximum number of unique job rows saved in one run. Range 1–5000. |
pageSize | integer | no | Runtime default: 0. No UI prefill. | Use the complete board response when 0. A positive value uses Lever skip/limit pages. Range 0–1000. |
continueOnError | boolean | no | Runtime default: true. No UI prefill. | Process independent targets after a technical failure and report a partial run. |
onlyNewSinceLastRun | boolean | no | Runtime default: false. No UI prefill. | Return only jobs that an earlier run with the same targets and filters has not returned. See Only new jobs. |
Nested filters
All filled groups must match (AND). Values within one group match any value (OR). Text matches ignore case and trim outer spaces. Empty arrays do not filter. Filters run after fetching source rows; a small result cap does not cap the source response size.
| Field | Type / limit | Default | Match rule |
|---|---|---|---|
filters.titleIncludes | array; up to 20 values | No restriction | Keep jobs whose title contains at least one of these values. Case-insensitive substring. |
filters.titleExcludes | array; up to 20 values | No restriction | Skip jobs whose title contains any of these values, e.g. intern. Case-insensitive substring. |
filters.locationIncludes | array; up to 20 values | No restriction | Keep jobs whose source location contains at least one of these values. Case-insensitive substring. Checks all locations. |
filters.locationExcludes | array; up to 20 values | No restriction | Skip jobs with any location that contains one of these values. Case-insensitive substring. |
filters.descriptionIncludes | array; up to 20 values | No restriction | Keep jobs whose posting text (opening, description, lists, additional) contains at least one value. Case-insensitive substring. Works with includeContent: false. |
filters.descriptionExcludes | array; up to 20 values | No restriction | Skip jobs whose posting text contains any of these values. Case-insensitive substring. |
filters.departments | array; up to 20 values | No restriction | Keep jobs whose source department equals one of these values. Case-insensitive exact value. |
filters.teams | array; up to 20 values | No restriction | Keep jobs whose source team equals one of these values. Case-insensitive exact value. |
filters.commitments | array; up to 20 values | No restriction | Keep jobs whose source commitment equals one of these values. Case-insensitive exact value. |
filters.workplaceTypes | array; up to 4 values | No restriction | Keep jobs with one of these source workplace types. |
filters.countries | array; up to 20 values | No restriction | Keep jobs whose source country is one of these ISO-2 values. Case-insensitive exact value. |
filters.createdAfter | string; UTC ISO date-time, e.g. 2026-10-01T00:00:00Z | No restriction | Only jobs created on or after this ISO date-time. Jobs with no source creation time do not match. |
filters.postedWithinDays | integer; 0–365 | No restriction (0) | Only jobs created in the last N days, counted from the run time. Jobs with no source creation time do not match. |
Filter strings have a maximum length of 200 characters; country values use two letters. workplaceTypes accepts remote, hybrid, on-site, unspecified.
Only new jobs
With onlyNewSinceLastRun: true the Actor remembers the job IDs it has handled and skips them in later runs. The memory is a named key-value store in your Apify account, lever-jobs-scraper-state, with one record per set of targets and filters. The first run returns all matching jobs as a baseline. A different target list or different filters start a new baseline. Jobs cut off by maxJobsPerTarget, maxTotalJobs or a charge limit stay new for the next run, and so do jobs that failed to save. Up to 50,000 IDs are kept per record; the oldest are dropped first. Delete the record to start over.
RUN_SUMMARY shows previouslySeenJobs, stateBaseline (true on the first run) and stateSaved. A board with no new jobs gets FILTERED_EMPTY. Skipped known jobs are billed like filtered jobs (filtered-job, $0.01 per 1,000), and a board with no new jobs gets one no-result-target.
Setting interactions
| Settings | Result |
|---|---|
maxJobsPerTarget: 0 + maxTotalJobs: 5000 | No per-board cap; stop at 5,000 unique useful rows across the run |
| Positive per-target and total caps | Apply both caps after filtering and dedupe; a per-target cap still allows later boards |
pageSize: 0 | Read one complete board response, subject to the 25 MiB response limit |
Positive pageSize | Use Lever skip/limit pages; stop at a short/empty page, cap or repeated-page error |
includeContent: false | Omit content and salary fields; lists is []; identity/category/link fields remain |
continueOnError: true | Continue independent targets after a source failure and show a partial summary |
onlyNewSinceLastRun: true | Jobs already returned by an earlier run with the same targets and filters are skipped and billed as filtered-job |
Examples
Small demo, also used for the output example below:
{"targets": ["leverdemo"]}
Two boards with a title filter and a per-board cap:
{"targets": ["leverdemo", "https://jobs.lever.co/palantir"],"filters": {"titleIncludes": ["engineer"]},"maxJobsPerTarget": 20,"maxTotalJobs": 40,"includeContent": true}
This saves up to 20 matching jobs from each board and 40 in total.
Job alert for remote engineering jobs that mention Kubernetes, without interns, only new since the last run:
{"targets": ["leverdemo", "https://jobs.lever.co/palantir"],"filters": {"titleIncludes": ["engineer"],"titleExcludes": ["intern"],"descriptionIncludes": ["kubernetes"],"workplaceTypes": ["remote"],"postedWithinDays": 30},"onlyNewSinceLastRun": true}
A filter may return no matches. EU input uses https://jobs.eu.lever.co/<board>. Public api.lever.co/v0/postings/<board> and EU API URLs are also accepted. HTTPS is required. Arbitrary hosts, userinfo, custom ports, fragments and traversal paths are rejected. Tracking query parameters are discarded.
Output
Dataset fields
Each row is one unique published job. The stable ID is lever:{region}:{boardSlug}:{encodedSourceJobId}. The same title can occur on distinct jobs; IDs control dedupe. observedAt is this Actor's observation time. createdAt comes from the source, converted to an ISO timestamp; it is not an update time.
| Field | Meaning | Type | Can be empty? | Example / enum | Source / notes |
|---|---|---|---|---|---|
id | Stable ID: lever:{region}:{board}:{postingId}. | string | no | lever:global:leverdemo:ad208490-… | Set by the Actor |
source | The public source name. | string | no | lever | Set by the Actor |
idRuleVersion | Version of the stable identifier rule. | string | no | v1 | Set by the Actor |
region | Global or EU public Lever instance. | string | no | global, eu | Set by the Actor |
boardSlug | Normalized public Lever site slug. | string | no | leverdemo | Set by the Actor |
boardUrl | Canonical public hosted board URL. | string | no | https://jobs.lever.co/leverdemo | Set by the Actor |
sourceJobId | Upstream Lever posting ID. | string | no | ad208490-4052-4f91-a57e-433f2d1e484b | Lever source, not guessed |
title | Published job title. | string | no | Customer Success Manager | Lever source, not guessed |
location | Primary source location, when present. | string | yes (null) | Atlanta, Georgia | Lever source, not guessed |
locations | Source location values. | array | can be [] | ["Atlanta, Georgia"] | Lever source, not guessed |
department | Source department, when present. | string | yes (null) | Customer Success | Lever source, not guessed |
team | Source team, when present. | string | yes (null) | Customer Success Team | Lever source, not guessed |
commitment | Source commitment, when present. | string | yes (null) | Regular Full Time (Salary) | Lever source, not guessed |
country | Source ISO-2 country, when present. | string | yes (null) | US | Lever source, not guessed |
workplaceType | Source workplace type or unspecified. | string | no | remote, hybrid, on-site, unspecified | Lever source, not guessed |
openingHtml | Source opening HTML when content is included. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever source, not guessed |
openingText | Plain opening text when content is included. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever plain field, or converted from HTML |
descriptionHtml | Source combined description HTML. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever source, not guessed |
descriptionText | Plain combined description. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever plain field, or converted from HTML |
descriptionBodyHtml | Source body HTML. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever source, not guessed |
descriptionBodyText | Plain body text. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever plain field, or converted from HTML |
lists | Source list sections with title, HTML and text. | array | can be []; [] with includeContent: false | [{"title": "Requirements", …}] | Lever source, not guessed |
additionalHtml | Source additional HTML. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever source, not guessed |
additionalText | Plain additional text. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever plain field, or converted from HTML |
salaryRange | Source salary range when provided. | object | yes; omitted with includeContent: false | min, max (number or null), currency, interval (string or null) | Lever source, not guessed |
salaryDescriptionHtml | Source salary note HTML. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever source, not guessed |
salaryDescriptionText | Plain salary note. | string | yes; omitted with includeContent: false | text or HTML from the posting | Lever plain field, or converted from HTML |
hostedUrl | Canonical public job page. | string | no | https://jobs.lever.co/leverdemo/ad208490-… | Lever source, not guessed |
applyUrl | Source application URL; never submitted by the Actor. | string | yes (null) | https://jobs.lever.co/leverdemo/ad208490-…/apply | Lever source, not guessed |
createdAt | Source creation time in ISO format. | string | yes (null) | 2026-09-09T11:01:39.000Z | Lever source, not guessed |
observedAt | Time this Actor observed the row. | string | no | 2026-10-28T05:00:00.000Z | Set by the Actor |
lists[] has title (section label), html (section body), and text (plain body), all strings. salaryRange is null or an object with min/max (number or null), currency/interval (string or null). No salary or location is guessed. workplaceType falls back to unspecified.
Missing source scalar values become null. Arrays can be empty. With includeContent: false, HTML/text and salary fields are omitted rather than set to null. HTML is source content; sanitize it before displaying it in your own web app. Plain text uses source plain fields when supplied, or HTML conversion. List body text is converted from list HTML. Some uncommon named HTML entities can remain encoded.
Example row
This trimmed row is from the leverdemo input above. Full descriptions and the remaining fields are in the Dataset.
{"id": "lever:global:leverdemo:ad208490-4052-4f91-a57e-433f2d1e484b","sourceJobId": "ad208490-4052-4f91-a57e-433f2d1e484b","boardSlug": "leverdemo","title": "Customer Success Manager","location": "Atlanta, Georgia","locations": ["Atlanta, Georgia"],"department": "Customer Success","team": "Customer Success Team","commitment": "Regular Full Time (Salary)","workplaceType": "hybrid","hostedUrl": "https://jobs.lever.co/leverdemo/ad208490-4052-4f91-a57e-433f2d1e484b","applyUrl": "https://jobs.lever.co/leverdemo/ad208490-4052-4f91-a57e-433f2d1e484b/apply"}
Reports and outcomes
The Output tab links to dataset and runSummary. They are links, not a second copy of the rows. The Actor writes RUN_SUMMARY in the default key-value store; it does not write a separate OUTPUT record.
RUN_SUMMARY includes schemaVersion, status, received/valid/duplicate/processed/unprocessed target counts, results, duplicateJobs, emptyBoards, filteredEmpty, notFound, technicalFailures, retries, rate-limit counts, invalid/filtered source row counts, previouslySeenJobs, stateBaseline and stateSaved (only with onlyNewSinceLastRun), limitReached, chargeLimitStop, charge events/mode, transport, timings, requests, bytes, failed target references, and targets[].
Each target entry has inputIndex, canonicalTarget, mode, region, status, source/emitted row counts, retries and errorCode; bytes/requests and duplicate references are present when relevant.
| Outcome | Dataset / report | What to do |
|---|---|---|
OK | Useful job rows | Export or use rows |
EMPTY_BOARD | No jobs returned by a valid source board | Check later if needed |
FILTERED_EMPTY | Source had jobs, filters matched none | Review filters |
NOT_FOUND | Board or exact posting returned HTTP 404 | Check the URL; posting may be closed |
INVALID_INPUT, DUPLICATE_TARGET | No result row for that target | Correct invalid input; duplicates need no retry |
LIMIT_REACHED | Saved rows retained; more jobs may exist | Review per-target/total/platform charge caps |
| Technical error | TIMEOUT, RATE_LIMITED, UPSTREAM_5XX, UPSTREAM_4XX, NETWORK_ERROR, BAD_CONTENT_TYPE, MALFORMED_JSON, SCHEMA_DRIFT, RESPONSE_TOO_LARGE, REDIRECT_ERROR, STORAGE_ERROR, ABORTED or UNPROCESSED | Read RUN_SUMMARY; fix input or retry later |
Run-summary status is SUCCEEDED, PARTIAL, FAILED or LIMIT_REACHED. Apify run status and summary status are separate: a partial run can finish on the platform and still have failed targets. A full technical source failure fails the platform run. Empty/missing targets do not prove that a company has no jobs elsewhere.
Pricing
Pay per event. Apify charges the standard apify-actor-start event automatically: $0.002 per start, one event per GB of run memory (minimum one). At the default 512 MB each run has one start event; 2 GB means two.
| Event | Free plan | Bronze | Silver | Gold |
|---|---|---|---|---|
Unique job row saved (unique-job-result) | $0.45 / 1,000 | $0.405 / 1,000 | $0.36 / 1,000 | $0.315 / 1,000 |
Job read but skipped by your filters (filtered-job) | $0.01 / 1,000 | same | same | same |
Board or job URL with no paid rows (no-result-target) | $0.0003 each | same | same | same |
no-result-target is charged once for a board or exact job URL that is not found, empty, or fully filtered. Duplicate rows, duplicate targets, invalid input and technical failures (timeouts, rate limits, Lever errors) are never charged. A partial run pays the start plus accepted useful rows and the small read events above.
| Run at 512 MB (Free plan) | Actor event charge |
|---|---|
| One missing board, 0 rows | $0.0023 |
| 10 useful jobs | $0.0065 |
| 100 useful jobs | $0.047 |
| 1,000 useful jobs | $0.452 |
| 5,000 useful jobs (current maximum per run) | $2.252 |
| A 4,000-job board filtered down to 0 rows | $0.0423 |
| A 4,000-job board filtered down to 100 rows | $0.086 |
The filtered-job fee applies to every job your filters skip, also when other jobs match. On a very large board with a narrow filter it can be a noticeable part of the bill.
These are event fees; the standard PPE tariff has no separate customer platform-usage surcharge. Check the run billing and your plan.
maxTotalJobs caps rows, not a bill in dollars. Use Apify's maximum total charge option (maxTotalChargeUsd in API calls) to limit total Actor event charges, including the start. At 512 MB, allow at least $0.00245 for one start and one useful job. The run stops cleanly when the limit is reached. This option does not limit all platform costs.
RUN_SUMMARY.chargeEvents counts job-result events; filteredJobEvents and noResultTargetEvents count the two small read events. The automatic start appears in the Apify run billing. The summary is not a customer invoice.
Limits
- Up to 50 targets and 5,000 saved jobs per run.
- Requests are paced one at a time with a 1-second host gap, up to 3 attempts, 20 seconds per request including body reading, up to 2 safe redirects, 25 MiB per response, and 1,000 pages per board. Large boards or repeated retries may exceed your platform timeout. Completeness means the public source response observed for your supplied boards, subject to these limits. Jobs may change during pagination.
- Only public published postings of boards you supply: no company discovery, global Lever search, private/internal or closed postings, applications, or closed/changed-job reports.
- Salary, location and dates are only what the source publishes; nothing is guessed.
API, export and integrations
- API: start a run with the Apify Actor run API and the same input JSON, then read the default Dataset.
- Export: Dataset export supports JSON and CSV, plus other Apify formats. Nested lists are best kept in JSON.
- Scheduling: you can use Apify scheduling with the same input. Each run has a start charge. Add
onlyNewSinceLastRun: trueto get only new jobs in each scheduled run; closed or changed jobs are not reported, so use the stableidin your system for those.
Use with AI agents (MCP)
- MCP server with only this Actor:
https://mcp.apify.com?tools=cliqtomedia/lever-jobs-scraper. - Smallest useful input:
{"targets": ["leverdemo"]}. - Key output fields:
id(stable job ID),title,location,team,hostedUrl(public job page);RUN_SUMMARY.targets[].statustells why a board gave no rows. - A small board such as the demo returns about 10 rows for about $0.0065 at 512 MB on the Free plan. Up to 50 targets and 5,000 rows per run; supply known board slugs, the Actor does not search Lever.
Troubleshooting
- URL rejected: use a supported HTTPS Lever host and one board or posting path. Do not paste a company's general careers URL.
- No rows: open
RUN_SUMMARY. CheckEMPTY_BOARD,FILTERED_EMPTY,NOT_FOUNDand technical errors separately. - Fewer rows: check caps,
chargeLimitStop, filters and per-target status. An early stop does not prove a complete board. - Timeout, block or rate limit: retry later with fewer targets. No login, browser or proxy bypass is provided.
- Missing salary or dates: the source may not publish them. They are not inferred.
FAQ
Do I need a Lever account?
No. Only public published postings are read. See Lever Postings API documentation.
Can I get every job on Lever?
You must supply known boards. There is no company discovery or cross-company global search.
Can I get EU jobs or one job URL?
Yes. Use an EU hosted board/job URL for EU mode. An exact posting URL returns that job if it remains public.
Does a repeat run return only new jobs?
Only if you turn on onlyNewSinceLastRun. Then the first run returns all matching jobs and later runs with the same targets and filters return only jobs not returned before. Without it, each run is a fresh snapshot.
Is no output free?
No. A zero-row run still has the $0.002 start charge at default 512 MB, plus $0.0003 for each board or job URL that gave no rows and $0.01 per 1,000 jobs skipped by your filters; there is no job-result event. Higher memory can increase the start count. Check your run's billing.
Can descriptions or locations be missing?
Yes. The source controls those fields. Check nulls, empty arrays and includeContent; do not treat missing fields as guessed values.
Related Actors
- Greenhouse Jobs Scraper & Monitor — the same job rows from companies that use Greenhouse boards.
- Ashby Jobs Scraper — public Ashby boards, for companies on Ashby instead of Lever.
- Workable Jobs Monitor & Scraper — Workable career pages, with job changes between runs.
- SmartRecruiters Jobs Scraper — SmartRecruiters boards, often used by large employers.
- Remote Jobs Aggregator — remote jobs from RemoteOK, We Work Remotely and Himalayas when you do not have a company list yet.
Support
Open an issue in this Actor's Apify Issues tab. Include the run ID, public input mode and the relevant RUN_SUMMARY target status. Do not share tokens, cookies, private URLs or sensitive payloads.
Lever identifies the source format. This product is not affiliated with or endorsed by Lever.

