Scrape LinkedIn jobs by keyword, location or company — no login, no cookies. Every posting returns the full description, salary, required skills, seniority and hiring-team contacts. Built for recruiters and sourcers. Export to CSV, JSON or Excel, run via API, or schedule runs.
All notable changes to the LinkedIn Jobs Scraper are documented here.
The format follows Keep a Changelog .
[0.0.40] - 2026-09-24
Fixed
A request that runs into more than one kind of trouble in a row — a busy moment, a dropped
connection, an answer that is not finished yet — no longer gets a fresh round of waiting each
time. Each job lookup and search page keeps one waiting budget from its first attempt to its
last, so a stuck one is reported as not checked on time instead of after a second full round of
waiting.
[0.0.39] - 2026-09-24
Changed
Docs: the related-actors table links the new LinkedIn People Search — find employees and
decision makers by job title, company, country and job function.
[0.0.38] - 2026-09-23
Fixed
When several of your runs start at the same moment, a job link now waits its turn (up to a few
minutes) instead of coming back empty.
A lookup that was accepted but never finished is now reported as not checked and not charged —
never as a closed posting or an empty search.
[0.0.37] - 2026-09-23
Fixed
A job link that could not be checked is no longer reported as a closed posting. When the
lookup for a link was turned away on every attempt, the run used to finish with the "no results"
advice, which suggests the posting has probably closed. It now says the link could not be checked
this time, that nothing was charged for it, and to re-run it in a few minutes. When only some of
your links could not be checked, you get the jobs that were checked plus a line saying how many
links to re-run.
A search that could not be run no longer reports that nothing matched. When a job search, or
the company lookup in Search Company Jobs, was turned away on every attempt, the run now says it
could not be run this time and that nothing was charged.
If a run has to stop early because of a limit on our side, it now stops cleanly and keeps what
it fetched. It used to keep trying and then finish as if your input had found nothing. You are
charged only for the jobs already in your dataset, and the message says your input was fine and
that the same input will work when you run it again later.
The "Welcome to the paid plan" message now appears only on your first paid run instead of on
every paid run, and the check-in after your third paid run can now appear. The count starts with
this version, so if you already ran this actor on a paid plan you see the welcome once more.
Changed
RUN_SUMMARY.stopReason now says how a run that returned no jobs ended — no_results,
all_filtered or Targets temporarily unavailable — where it used to say the run completed.
RUN_SUMMARY.skippedUnchecked counts the job links that could not be checked this time.
[0.0.36] - 2026-09-10
Changed
Clarified wording in the README, this changelog, the input form, the output column titles and
the live status page description. Nothing changes in how the actor runs, what it returns or what
it costs.
Fixed
When a run fails for a reason on our side, the error message now stays short and plain.
[0.0.35] - 2026-09-07
Fixed
When a run stops early and explains why, the explanation is now in the run log instead of only
in the Storage tab. The log used to show one line — the heading of the message — and told you
to open Storage to read the rest. The rest is where the useful part lives: which link shape Mode 2
accepts, and that Mode 1 finds the same jobs from a title and a location. One customer pasted
company-careers links 33 times over eight days and never saw it. Nothing had been charged for
those runs, and nothing is charged now — the only thing that changes is that the answer arrives
where you are already looking.
[0.0.34] - 2026-09-01
Fixed
A run that ran alongside your other runs could come back empty-handed, and now waits instead.
When several of your runs are working at the same time, requests start being turned
away. The run used to try twice more, five and ten seconds apart, and then give up. A run now
waits longer and up to five times, and each run picks its own waiting time rather than all of
them counting to five together and arriving back at the same instant. If the response says how long
to wait, that is what the run waits.
The extra waiting is capped: at most 30 seconds at a time and 75 seconds in total for any one
piece of data, after which the run moves on rather than holding your run open. A busy run may
therefore finish a little slower than before — it is waiting where it used to fail.
[0.0.33] - 2026-08-26
Fixed
A run that named its own cause was being filed as a clean completion. The zero-row
fallback stop reason (no_results) overwrote whatever the mode branch had already set, so
the off-LinkedIn run shipped in 0.0.32 explained itself in USER_MESSAGE and then recorded
itself as completed. no_results now means what it says — nothing came out and nothing
said why — and only replaces the untouched default.
[0.0.32] - 2026-08-26
Added
Mode 2 now tells you when a link is not a LinkedIn posting, by name. A link on a
company careers site (Workday, Lever, UltiPro, Oracle Cloud, Indeed, a company's own
careers page…) is recognised before any lookup is made: the run skips it, charges nothing
for it, and the new not_linkedin_urls_v1 message quotes the host it saw and names the
next step — find the same role on LinkedIn, or use Mode 1 (Search jobs) or Mode 3
(Search company jobs). Previously such a run spent a lookup, returned nothing, and was
handed a list of three possible causes to choose between.
RUN_SUMMARY carries skippedForeignHosts — links skipped before any lookup. Kept apart
from skippedEmpty, which counts links that were tried and came back empty: a dead
LinkedIn posting and a careers-site URL are different outcomes with different fixes.
A run whose links are all off-LinkedIn now reports a stop reason that says so, instead of
being indistinguishable from a search that legitimately found nothing.
A partially off-LinkedIn list is handled too: the LinkedIn links do their work and the
rest are named in a line appended to whatever the run had to say.
Changed
The job id is now read correctly from the canonical LinkedIn URL form. LinkedIn writes
…/jobs/view/<role-slug>-<id>; the id was only recognised when it followed /jobs/view/
immediately, so for those links a truncated URL was used in its place — in the run's target
label and, when the fetched job data omitted the id, in the job_urn column of a withheld
preview row. Both now carry the id.
The "Job posting URLs" field says that links must be on linkedin.com and what to use
instead when they are not.
[0.0.31] - 2026-08-25
Added
Two documented surfaces that already shipped but were never written down.📡 Live status & storage records names the live status page and the three key-value
records any run writes (RUN_SUMMARY, USER_MESSAGE, FREE_LIMITS_APPLIED), so an
unattended pipeline can branch on them instead of parsing the log.
🤖 Programmatic / API use shows the actual calls: run-and-collect in one request,
fire-and-poll for large company sweeps, reading a run's records, scheduling via a Task,
and webhooks.
A 🧭 When to use it section, with every bullet naming a field or filter the Actor
already ships.
An opening paragraph saying what LinkedIn's own job APIs do not give you, and what this
Actor returns instead.
Changed
The detail-column count was wrong on every surface that stated it. The README claimed
"36 detail fields" in three places and the input schema said "36 fields per row"; the
Actor returns 33 detail columns. Corrected, and the total is now stated once and
honestly: 46 columns — 10 on every search row, 33 more on an enriched row, plus
row_status / why_withheld and the input echo.
The payload is described by what each column decides rather than by how many there are.
The output sample now matches the dataset schema exactly (46 keys): row_status,
why_withheld and hq_address_line2 were missing from it.
The output section states what a free run held back, and the FAQ answer about the per-run
limit now mentions the preview rows instead of only the USER_MESSAGE record.
The README's H1 matches the Actor's Store title.
🔑 Use cases became 🧭 When to use it and moved up, ahead of the example tasks.
[0.0.30] - 2026-08-25
Added
Withheld free-plan preview rows. When a free run hits the 20-job cap with matches
remaining, up to 5 already-fetched jobs from the same page are now published at the end of
the dataset as preview rows: row_status = 'withheld_free_plan', title/company/location
real, links/salary/details locked, and a why_withheld sentence naming exactly what was
held back. Preview rows are never charged and never counted in run totals. Every normal
row now carries row_status = 'delivered' / why_withheld = 'N/A', so previews are
filterable. Two new dataset columns appended last; both dataset views updated.
Mode 2 (Fetch Job Details): links the cap left unprocessed are echoed back as preview rows
(your own URLs, nothing else), so the skipped list is visible in the dataset itself.
Changed
A free run truncated by the cap now reports stopReason = 'free_cap_reached'
(category free_limit) instead of a plain completion.
The free-cap message counts Mode-2 withheld links honestly: only links never attempted are
"not processed" — dead links that returned nothing are no longer counted as withheld.
README: the Free plan section is now a Free-vs-paid table naming exactly what a paid plan
unlocks.
[0.0.29] - 2026-08-17
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.28. Saved tasks continue to work identically.
[0.0.28] - 2026-08-17
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.27. Saved tasks continue to work identically.
[0.0.27] - 2026-08-12
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.26. Saved tasks continue to work identically.
[0.0.26] - 2026-08-12
Maintenance build — no user-facing changes. Input schema, output dataset
columns, KVS records, console output, error messages, defaults, and pricing
are all unchanged from 0.0.25. Saved tasks continue to work identically.
[0.0.25] - 2026-08-10
Fixed
A failed run no longer names the exact request that failed. When a request was refused, the
run's failure reason spelled out the technical address that had been called, and that reason is
stored in RUN_SUMMARY and shown with the run. It now says only that the request was refused.
[0.0.24] - 2026-08-10
Changed
The free-plan limit ids listed in the run's FREE_LIMITS_APPLIED storage record now use one
shared vocabulary across all our actors, so the same limit reads the same wherever you meet it.
The human-readable message on each entry is unchanged.
[0.0.23] - 2026-07-30
Maintenance build — no change to input, output or pricing.
[0.0.22] - 2026-07-29
Changed
The Storage tab now names the records the run writes — the run summary, the plain-language
explanation of what happened, and the free-plan caps applied — instead of showing bare keys.
The Store listing now says what this actor returns — full description, salary, required
skills, seniority and hiring-team contacts on every posting — and the price line shows the
per-job price instead of a generic label.
[0.0.21] - 2026-07-28
Fixed
The status page is saved at all now. Its saved copy was being rejected on every single run,
so there was nothing to fall back on once the run's container went away.
The status page now keeps up while a run is going. Its saved copy was only written twice —
once at the start and once at the end — so anyone opening it mid-run saw the run as it looked at
second zero. It now refreshes every ten seconds.
The "Live status" link now works after a run has finished. It pointed at the run's own
container, which the platform shuts down as soon as the run ends, so opening it later showed
nothing. It now opens the saved copy of the page, which stays available for as long as the run's
storage does.
Removed a storage record from the actor's schema that this actor never writes.SKIPPED_ITEMS
was declared but never produced, so tools reading the schema expected a record that was never
there.
[0.0.20] - 2026-07-06
Changed
Every "Upgrade" link in run messages now says what's behind it: paid plans start at $29/mo with $29 in platform credits, and the link opens your plan page in Apify Console.
[0.0.19] - 2026-07-06
Fixed
The "Upgrade" link in run summaries now opens your Apify plan page directly (the old link form could land on the wrong billing tab).
[0.0.18] - 2026-07-02
Added
When some job links return nothing, the run now says how many. A Fetch Job Details run with a mix of live and expired links previously reported only the rows it saved — now the run report and the completed screen show "N of your M job links returned nothing — likely closed, filled, or removed postings", with a reminder that empty links are not charged. The run summary also carries the count.
[0.0.17] - 2026-07-02
Changed
README "Example tasks" now links the new "Scrape jobs by company on LinkedIn" ready-to-run task (six one-click examples total). No code changes.
[0.0.16] - 2026-07-02
Fixed
Mode 3 (Search Company Jobs) now returns what companies actually list. Two bugs made most company searches come back empty:
Leaving the keyword field blank silently searched a default query instead of returning every open role. Blank keywords now return the company's complete job listing, as the field always promised.
Results were silently limited to the United States unless you changed the location. Mode 3 now searches all locations by default; pick a Mode 1 location field to narrow.
Added
Empty company searches now explain themselves — the run report and live status screen show each company's live open-roles count, so you can tell "this company lists no jobs on LinkedIn" apart from "my keywords filtered everything out".
New "Scrape jobs by company" example task; FAQ entry on getting every open role at a company.
Changed
Mode 3 documentation rewritten around the fixed behavior: blank keywords = complete listing, worldwide by default, cost guidance for large companies.
[0.0.15] - 2026-07-02
Added
Example tasks — five ready-to-run, pre-configured searches linked from the README (by keyword, Data Analyst, Product Manager, remote jobs, Software Engineer). One click, no setup.
The run tells you what you're missing — when a free run hits the plan cap, the run report now shows exactly how many jobs matched your search and how many more are waiting, with a one-step path to the full result set.
Recovery screen for zero-result runs — instead of a generic completion screen, a run that finds nothing now shows the most likely cause, the top fix, and a starter search that always returns jobs. The no-results report also leads with that starter search.
New FAQ entries — no LinkedIn account/cookies/login needed; how many jobs per run; bulk-enriching job URL lists; scheduling a daily search.
Tips & Best Practices and Disclaimer sections in the README; clearer in-form guidance on both search-keyword fields.
Changed
Free plan now returns up to 20 jobs per run (was 50). When a search matches more, the run report says exactly how many — upgrade and re-run the same input for the full set.
Store title and description now lead with what the data is for: salary, skills, and hiring-team contacts for recruiters, sourcers, and lead-gen teams.
Mode 3 (Search Company Jobs) documentation now sets honest expectations — many companies have no open roles at any given moment.
Fixed
Truncated Store description (ended mid-sentence with "…").
Welcome message wrongly said scheduling was paid-only — free plans can schedule tasks with saved input too.
[0.0.14] - 2026-05-28
Fixed
Helpful message when Fetch Job Details returns nothing — if a job link can't be pulled, the run now explains the likely cause (the posting was closed, filled, or removed; or the link isn't a job-view URL like https://www.linkedin.com/jobs/view/<id>) and how to copy a valid one, instead of showing the generic welcome message. Search mode already did this — Fetch Job Details now does too. Empty detail pulls are not charged.
[0.0.13] - 2026-05-21
Added
Helpful message when a search returns no jobs — if Search Jobs or Search Company Jobs finds nothing, the run now explains the most likely reasons and the highest-impact fixes (trim your keywords to the core job title, widen the date range, turn off Easy Apply / Under 10 applicants, broaden experience levels) instead of finishing silently with an empty dataset. Empty results are not charged.
Changed
The Job keywords field now notes that extra words (seniority, degree, e.g. "fresher") sharply narrow results and can return nothing.
[0.0.12] - 2026-05-21
Fixed
Multiple job titles in one search — a comma-separated keyword list (e.g. Risk Analyst, Data Analyst, Financial Analyst) is now treated as an OR search that returns jobs matching any of the titles. Previously the whole comma string was sent as a single literal phrase, which matched nothing and returned zero rows. Applies to Mode 1 (Search Jobs) and Mode 3 (Search Company Jobs).
Custom Location with several places — a comma list in Custom Location (e.g. Poznań, Łódź) now resolves to the first place LinkedIn recognises instead of silently falling back to the whole country.
[0.0.11] - 2026-05-18
Added
State / province / region dropdown — narrow Mode 1 to a single subdivision (~1500 entries covering 70 top markets, sourced from LinkedIn's own canonical ADMIN_DIVISION_1 IDs).
Major city dropdown — narrow Mode 1 to a single city (top ~1000 global cities by population, sourced from LinkedIn's canonical CITY IDs).
Custom Location free-text field — type ANY LinkedIn-indexed location (city / town / neighborhood / region) and the actor resolves it live. Power users can paste a numeric LinkedIn geoId directly. Closes the long-tail gap for places not in the curated dropdowns (Cluj-Napoca, Pune, Tartu, etc.).
Changed
Geo resolution now cascades through four fields. Priority: Custom Location → City → State → Country. The most specific non-empty filter wins. Country dropdown remains the always-default fallback.
[0.0.10] - 2026-05-18
Maintenance build — no user-facing changes.
[0.0.9] - 2026-05-18
Changed
Country dropdown expanded to 198 entries — full ISO-3166-1 sovereign-state coverage. GeoIds resolved canonically against LinkedIn's own public typeahead API (the same source that powers the autocomplete on linkedin.com/jobs). No more "your country isn't in the list" gaps.
[0.0.8] - 2026-05-18
Changed
Country dropdown expanded from 23 → 28 entries after cross-referencing a community-curated mapping. Added: China, Italy, Russia, South Korea, United Arab Emirates. Two prior probe-rejected geoIds were re-investigated and revealed to be these countries (initial probes misread the top-row locations).
[0.0.7] - 2026-05-18
Changed
"Location (LinkedIn geo code)" is now a Country dropdown with 23 probe-verified top markets. Previously a numeric input that asked customers to extract the geoId from a linkedin.com URL — now they pick a country name from a list. Default is United States.
Default country geoId updated to the real United States value (probe-verified). The previous default returned ~500K mixed-region results dominated by Vietnam — it was a supra-regional bucket, not a country filter.
Notes
LinkedIn's geo filter is loose; even with a country selected, some rows from adjacent markets may appear. The field description discloses this.
[0.0.5] - 2026-05-18
Added
Industries multi-select dropdown on Mode 1 (Search Jobs) and Mode 3 (Search Company Jobs), sourced from the 434-entry canonical LinkedIn V2 industry taxonomy. Pick one or more industries to narrow the search to a specific sector.
Notes
Verified with live searches that the industry filter accepts industry names end-to-end (e.g. Software Development narrowed the broad "engineer" pool from 499,684 → 95,375 jobs with software companies up top; Accounting narrowed to 4,017 with PwC / James Moore; Higher Education to 1,332 with Penn State / Duke).
[0.0.4] - 2026-05-18
Fixed
Dataset schema validation no longer rejects Mode 2 rows. Three type mismatches reconciled: expired, closed, remote_allow, and hiring_team now accept every value type they actually arrive in.
[0.0.1] - 2026-05-18
Added
Initial private build with three operation modes — Search Jobs, Fetch Job Details, and Search Company Jobs.
PAY_PER_EVENT pricing with a single JOB_ANALYZED event ($0.030/job) across all modes.
Seven post-fetch filters — title contains / NOT contains, company name allow-list, location contains, minimum salary, posted-within-N-days, remote-only.