LinkedIn Jobs Scraper By Multiple Keywords & Locations avatar

LinkedIn Jobs Scraper By Multiple Keywords & Locations

Pricing

from $4.99 / 1,000 results

Go to Apify Store
LinkedIn Jobs Scraper By Multiple Keywords & Locations

LinkedIn Jobs Scraper By Multiple Keywords & Locations

Collect job listings from LinkedIn with full metadata. Great for tracking industry demand, monitoring hiring trends, and building recruitment intelligence tools.

Pricing

from $4.99 / 1,000 results

Rating

0.0

(0)

Developer

API Empire

API Empire

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

1

Monthly active users

2 days ago

Last modified

Share

LinkedIn Jobs Scraper — Job Listings, Salaries and Employer Data

LinkedIn Jobs Scraper extracts public LinkedIn job postings into structured JSON — search matrix in, typed rows out. Give it a list of job titles and a list of locations and it searches every title × location combination, de-duplicates jobs that surface in more than one search, and stamps each row with the exact search that found it. Every row carries the listing itself, the employer that posted it, and — where LinkedIn shows one — the person who posted it. No LinkedIn account or login is required. Point it at your title and city lists, start the run, and the dataset fills with normalized job, company and poster fields ready for a spreadsheet, a database or an LLM prompt.

What is LinkedIn Jobs Scraper?

LinkedIn Jobs Scraper is an Apify Actor that turns LinkedIn's public job search into a structured dataset. It reads LinkedIn's logged-out "guest" job surfaces — the same search results and job pages an anonymous visitor sees — and returns each posting as a typed JSON row, including the employer's public details and, when LinkedIn exposes one, the job poster's name and profile.

No LinkedIn account, cookie or session is needed to run it; the Actor never logs in.

  • Search a title × location matrix — every job title against every location, one query per pair
  • Screen results by title before they're fetched, with an include list and an exclude list
  • Restrict a run to specific employers by name, LinkedIn URL or numeric company ID instead of the matrix
  • Filter by date posted, work type, contract type and experience level on every search in the matrix
  • Export to JSON, CSV, Excel or XML, or read the dataset straight through the Apify API

What data does LinkedIn Jobs Scraper collect?

Each dataset row carries three groups of data in one flat record: the job posting itself, the employer that listed it, and the person who posted it when LinkedIn names one.

Data TypeKey FieldsJSON Field Names
Job listingtitle, location, salary, posted date, applicant count, contract/experience/work typetitle, location, salary, publishedAt, applicationsCount, contractType, experienceLevel, workType
Employer datacompany name, company profile URL, company ID, industry sectorcompanyName, companyUrl, companyId, sector
Job poster dataposter's full name, poster's LinkedIn profile URLposterFullName, posterProfileUrl
Search-matrix provenancewhich title/location pair found this job, the radius usedsearchKeyword, searchLocation, searchRadiusMiles

Need more LinkedIn data?

Two companion API Empire Actors extend what you get from the posterProfileUrl and companyUrl fields this scraper returns: LinkedIn Phone Number Scraper & Email Finder turns a poster or employee profile URL into contact details, and LinkedIn Company URL - Mass Profile Finder expands a company URL into the people behind it. Neither is required — this Actor's output is complete on its own.

Why not build this yourself?

LinkedIn does not offer a self-serve public API for job search — the Talent/Jobs APIs it does publish require a partnership agreement, not an API key you can sign up for, so scraping the public guest surfaces is the practical alternative for ad-hoc or bulk job data. The cost of doing that yourself shows up in the details, not the request itself.

LinkedIn's guest job-detail fragments declare charset=utf-8 in the HTTP header but carry no in-document meta charset, so handing the raw bytes to an HTML parser makes it silently fall back to Latin-1 and mangle every non-ASCII character in a title, company name or description. The guest search endpoint serves 10 result cards per page, not the 25 many scrapers assume, so a wrong page-step assumption silently skips the majority of results without erroring. Pay is never published as structured data on the guest surfaces, so a usable salary field means writing a context-anchored parser that can tell "$150,000 per year" from "$150 monthly commuter reimbursement" and "raised $20M in funding" apart — a bare currency regex gets all three wrong. And the poster's name sits inside a nested <span> on every listing, so a selector that reads only an anchor's direct text returns an empty string on every row. None of this is exotic, but it's the kind of thing that only surfaces once you've parsed a few hundred real listings.

Why do developers and teams scrape LinkedIn jobs?

Job posting data serves a narrower set of audiences than social or e-commerce data, but each one has a concrete, recurring workflow behind it.

For recruiters and talent acquisition teams

A talent team covering multiple offices runs the same role list — "Software Engineer", "Data Analyst", "Product Manager" — against every city they hire in, in one matrix run, instead of repeating a manual LinkedIn search per city. titleExcludes strips seniority levels they're not hiring for, and searchKeyword/searchLocation on every row tells them which office pairing produced which listing without cross-referencing anything.

For sales and business development teams

Sales teams selling to companies that are actively hiring use the employer fields — companyName, companyUrl, sector — as a hiring signal: a company posting for "DevOps Engineer" roles across several cities is a live buying signal for infrastructure or tooling vendors. Restricting the run with companyInput turns the same Actor into an account-monitoring feed for a target list.

For labour-market and compensation researchers

Researchers tracking demand for a role or skill across a region run one job title against a list of cities and read location, workType, experienceLevel and the parsed salary field off the results, keeping the analysis to publicly posted listings rather than internal survey data. Because salary is null whenever LinkedIn's listing states no pay, the field never manufactures a number a posting didn't provide.

For developers building data products

Developers piping job data into a job board, an ATS integration or a scheduled monitoring feed get a stable JSON schema on every run — same 27 keys, same types — so a downstream pipeline built against this Actor doesn't need updating when LinkedIn changes its page layout underneath it.

🧭 How to scrape LinkedIn jobs (step by step)

  1. Open LinkedIn Jobs Scraper on the Apify Console and click Try for free
  2. List your job titles in Job titles to search (jobTitles) and your cities in Locations to search (searchLocations) — nothing is required, but leaving both empty falls back to the single legacy keywords/location search
  3. Set Jobs per search (maxJobsPerSearch) for the budget per title × location pair, and narrow the run with Date posted, On-site / Remote, Job type or Experience level if you want fewer, more targeted results
  4. Click Start and watch rows stream into the dataset as each job is scraped
  5. Download the dataset as JSON, CSV, Excel or XML, or pull it through the Apify API

What to do when LinkedIn changes its structure

The Actor is maintained, and its output schema is the contract: field names and types stay stable across LinkedIn layout changes so an integration built against this Actor keeps working without code changes on your end.

⬇️ Input

All parameters are optional — there is no required field, so a default run searches "Software Engineer" jobs in "United States".

ParameterRequiredTypeDescriptionExample Value
jobTitlesNoarrayOne job title per line, searched against every location below. Duplicates and blank lines are ignored.["Software Engineer", "Data Analyst"]
searchLocationsNoarrayOne location per line, paired with every job title above.["Austin, Texas, United States", "London, England, United Kingdom"]
searchRadiusMilesNointegerSearch radius in miles around each location. Minimum 0, maximum 100, default 0 (LinkedIn's own default radius).25
maxJobsPerSearchNointegerJob budget for EACH title × location pair, not the whole run. Minimum 1, maximum 1000, default 20.50
titleIncludesNoarrayKeep only jobs whose title contains at least one of these words (case-insensitive). Empty = keep every title.["engineer", "developer"]
titleExcludesNoarrayDrop any job whose title contains one of these words. Wins over titleIncludes.["senior", "principal", "manager"]
companyInputNoarrayEmployer name, LinkedIn company URL, or numeric company ID. When non-empty, replaces the title × location matrix with a company-restricted search.["Google", "https://www.linkedin.com/company/google/", "1441"]
publishedAtNostringDate-posted filter. Enum: "" (Any time), "r86400" (Past 24 hours), "r604800" (Past week), "r2592000" (Past month). Default ""."r604800"
workTypeNostringWork arrangement filter. Enum: "" (Any), "1" (On-site), "2" (Remote), "3" (Hybrid). Default ""."2"
contractTypeNostringEmployment-type filter. Enum: "" (Any), "F" (Full-time), "P" (Part-time), "C" (Contract), "T" (Temporary), "I" (Internship), "V" (Volunteer). Default ""."F"
experienceLevelNostringSeniority filter. Enum: "" (Any), "1" (Internship), "2" (Entry level), "3" (Associate), "4" (Mid-Senior level), "5" (Director), "6" (Executive). Default ""."3"
geoIdNostringLinkedIn numeric location geoId, sent with every search in the matrix. Applies to all locations at once, so best left empty when searching multiple cities. Default ""."103644278"
keywordsNostringSingle keyword string, used only when jobTitles is empty. Default "Software Engineer"."Backend Developer"
locationNostringSingle location string, used only when searchLocations is empty. Default "United States"."United States"
maxJobsNointegerTotal cap for the legacy single search and for company-restricted runs. Minimum 1, maximum 1000, default 20. Not used as a global cap when the title × location matrix is active.100
sortOrderNostringKept for backward compatibility only — LinkedIn's public job endpoint ignores sorting. Enum: "" (Default), "relevance" (Most relevant, ignored), "date" (Most recent, ignored). Default "".""
proxyConfigurationNoobjectApify Proxy settings. Default is no proxy — LinkedIn's guest job surfaces are reachable directly. Enable only if you see blocks or empty pages.{"useApifyProxy": false}

Example input

{
"jobTitles": ["Software Engineer", "Data Analyst", "Product Manager"],
"searchLocations": ["Austin, Texas, United States", "Chicago, Illinois, United States"],
"searchRadiusMiles": 25,
"maxJobsPerSearch": 50,
"titleIncludes": [],
"titleExcludes": ["senior", "principal"],
"companyInput": [],
"publishedAt": "r604800",
"workType": "",
"contractType": "",
"experienceLevel": "",
"geoId": "",
"keywords": "Software Engineer",
"location": "United States",
"maxJobs": 20,
"sortOrder": "",
"proxyConfiguration": { "useApifyProxy": false }
}

Most common input mistake: treating maxJobsPerSearch as a cap for the whole run. It is a budget per title × location pair — 3 titles × 2 locations at a budget of 50 can pull up to 300 jobs before cross-search duplicates are removed, not 50.

How the search matrix works

jobTitles and searchLocations are combined as a full cartesian product — every title is paired with every location and searched as its own independent query. 3 titles × 2 locations produces 6 searches, not 3 or 2; 10 titles × 10 cities produces 100. Leaving either list empty falls back to the single legacy keywords/location search instead of the matrix.

This directly drives what you're charged for. Each of those searches pulls up to maxJobsPerSearch job IDs, so the raw total considered is pairs × maxJobsPerSearch before anything is removed. Two things shrink that number before it becomes billed rows:

  • Cross-search de-duplication. If the same job ID turns up in more than one search — a real possibility once cities or titles overlap — only the first search to find it keeps it; later searches log it as a duplicate and it is not scraped or billed twice. The per-search breakdown (jobsFound, newAfterDedupe, duplicatesOfEarlierSearches) is written to the run's key-value store as SEARCH_SUMMARY so you can see exactly which pair contributed what.
  • Title screens. titleIncludes/titleExcludes are checked against the job's title on the search card, before any per-job detail request is made, so a screened-out job is never fetched and never charged. In one verified pass documented in the Actor's source, 40 candidate jobs were screened down to 28 — 12 were dropped by the title screens before a single detail request was sent for them, so only 28 detail requests (and potential charges) were made instead of 40.

Only jobs that survive de-duplication and the title screens, and that are successfully fetched and parsed, generate a charged row_result event.

⬆️ Output

Every job is one dataset row, and the row the Actor pushes carries exactly the same 27 keys the dataset's default view displays — there is no hidden superset here. Missing values come back as null rather than an empty string or a missing key, so a downstream consumer never needs a presence check. Export as JSON, CSV, Excel or XML, or read the dataset through the Apify API.

Field NameDescription
searchKeywordJob title that found this job (the search side of the matrix pair). null on the legacy single search.
searchLocationLocation that found this job. null on the legacy single search.
searchRadiusMilesRadius, in miles, applied to that search. null when the input was left at 0.
idLinkedIn's numeric job posting ID.
titleJob title from the job detail page.
companyNameEmployer name.
locationJob location, from the detail page's location bullet, falling back to the search card.
publishedAtPosting date. Prefers LinkedIn's exact ISO date from the search card; only reconstructed from the relative "posted X ago" string when the job wasn't discovered via a card.
postedTimeThe raw relative string as LinkedIn shows it (e.g. "1 week ago").
salaryPay figure, only when the description states one in a genuine compensation context. null on the common case where LinkedIn states no pay — this is prose-parsed, not structured LinkedIn data.
applicationsCountApplicant count as a bare number.
applicantsCountTypePrecision of that count: exact ("119 applicants"), at_least ("Over 200 applicants"), or fewer_than ("Be among the first 25 applicants").
applicantsTextThe raw applicant bullet text LinkedIn displayed.
contractTypeEmployment type, as LinkedIn's own "Employment type" field states it (e.g. "Full-time").
experienceLevelSeniority level, as LinkedIn's own "Seniority level" field states it.
workTypeLinkedIn's own "Job function" field — despite the name, this is not the on-site/remote/hybrid filter value.
sectorLinkedIn's own "Industries" field.
jobUrlDirect URL to the job posting.
companyUrlEmployer's LinkedIn company page URL.
companyIdEmployer's numeric LinkedIn company ID.
benefitsBenefit keywords detected in the description text (health insurance, 401(k), remote, etc.) — a text signal, not a structured LinkedIn benefits field, since LinkedIn's guest surfaces publish no structured benefits block.
posterFullNameFull name of the person who posted the job, when LinkedIn names one.
posterProfileUrlLinkedIn profile URL of the job poster, when present.
descriptionFull job description as plain text.
descriptionHtmlFull job description with LinkedIn's original HTML markup preserved.
errorReasonnull on a successful row. On an uncharged accounting row, a code such as throttled_999, http_403, timeout or unparseable_page.
scrapedAtUTC timestamp (ISO 8601) when this row was scraped.

Scraped job listing

{
"searchKeyword": "Software Engineer",
"searchLocation": "Austin, Texas, United States",
"searchRadiusMiles": 25,
"id": "3987654321",
"title": "Senior Backend Software Engineer",
"companyName": "Example Tech Inc.",
"location": "Austin, Texas, United States",
"publishedAt": "2026-07-18",
"postedTime": "1 week ago",
"salary": "$120,000 - $150,000/yr",
"applicationsCount": "119",
"applicantsCountType": "exact",
"applicantsText": "119 applicants",
"contractType": "Full-time",
"experienceLevel": "Mid-Senior level",
"workType": "Engineering",
"sector": "Software Development",
"jobUrl": "https://www.linkedin.com/jobs/view/3987654321",
"companyUrl": "https://www.linkedin.com/company/example-tech",
"companyId": "1441123",
"benefits": "health insurance, 401(k), remote",
"posterFullName": "Jordan Lee",
"posterProfileUrl": "https://www.linkedin.com/in/jordan-lee-example",
"description": "We're looking for a Senior Backend Software Engineer to join our platform team...",
"descriptionHtml": "<p>We're looking for a Senior Backend Software Engineer...</p>",
"errorReason": null,
"scrapedAt": "2026-07-25T14:02:11Z"
}

A job that could not be fetched or parsed is still written to the dataset as an accounting row — same 27 keys, every job field null, errorReason set to a code such as throttled_999, http_403 or unparseable_page, and the same searchKeyword/searchLocation provenance stamps as a real row. These rows are not charged: filter them out of any downstream count with errorReason == null.

How does LinkedIn Jobs Scraper work?

The Actor talks to LinkedIn's public "guest" job endpoints directly with aiohttp and parses responses with lxml — there is no headless browser and, by default, no proxy. Search results come from GET /jobs-guest/jobs/api/seeMoreJobPostings/search, and job details come from GET /jobs-guest/jobs/api/jobPosting/{jobId}, the same surfaces LinkedIn serves to a logged-out visitor.

A run for each title/location pair starts by warming the session — fetching linkedin.com once so the endpoint issues its guest cookies — then paginates the search endpoint in steps of 10 results, which is the endpoint's real page size regardless of what the UI shows. Pagination stops when the per-search budget is reached, when a page returns the same job IDs as the page before it (LinkedIn's own signal that a query is exhausted), or at start=1000, the point where the endpoint starts returning HTTP 400.

Job detail fetches run at a concurrency of 2 with small randomized delays between requests, in batches of 3 with a pause between batches — deliberately conservative pacing rather than throughput-tuned. Every request goes through a retry ladder: LinkedIn's HTTP 999 response is treated as a throttle, not a block, and gets a longer backoff before retrying; HTTP 403 or 429 on the very first attempt of a run triggers an automatic escalation to Apify Proxy, trying a datacenter group first and falling back to residential after repeated failures, if proxy use is enabled in proxyConfiguration. With no proxy configured, blocked responses are simply retried with backoff.

Response bytes are explicitly decoded as UTF-8 before parsing, because LinkedIn's guest fragments declare charset=utf-8 in the HTTP header but not in the document itself — skipping that step is what causes accented characters and typographic punctuation to come out mangled in titles, company names and descriptions. Only publicly visible listing data is read; no account, cookie or authenticated session is ever used.

How does LinkedIn Jobs Scraper compare to other LinkedIn scrapers?

FeatureLinkedIn Jobs ScraperGeneric alternative
Multi-title × multi-location search✅ Cartesian matrix over jobTitles and searchLocations, one query per pair, cross-search de-duplicationTypically one keyword and one location per run
Search radiussearchRadiusMiles maps to LinkedIn's own distance parameter, honored per locationOften not exposed at all
Title screening before fetchtitleIncludes/titleExcludes run against the search card before a detail request, so a rejected job costs nothingNot commonly documented
Output formatTyped, normalized JSON on every run — no HTML, no selectorsVaries by scraper
Login required✅ No — logged-out guest surfaces onlyVaries; some require a LinkedIn session cookie

Checked on the Apify Store on 2026-07-25: curious_coder/linkedin-jobs-scraper's own listing documents a "Split search urls by location" feature to work around LinkedIn's roughly 1,000-result-per-search ceiling, and lists a broader field set built around opening a LinkedIn search URL directly. lntb/linkedin-jobs-scraper---multiple-titles-locations-in-one's listing advertises multi-title and multi-location search similarly to this Actor, plus apply-URL extraction, and bundles an unrelated third-party resume service in its README. bebity/linkedin-jobs-scraper's listing is a single-keyword, single-location tool with a short README and no documented multi-search matrix.

If you're building an AI agent or RAG pipeline, the output format row is the decision-maker — parsing HTML inside an agent loop is a reliability failure mode, not a feature.

⚠️ How many results can you scrape with LinkedIn Jobs Scraper?

There is no fixed dataset-wide cap in the Actor itself, but LinkedIn's public guest search endpoint stops paginating a single query at start=1000 (it returns HTTP 400 beyond that), so roughly 1,000 results is the real ceiling per individual title × location search, regardless of what maxJobsPerSearch is set to. Splitting one broad search into a title × location matrix is how you get past that ceiling — 10 titles × 10 cities is 100 independent searches, each with its own ~1,000-result headroom, not one search sharing a single 1,000-result budget.

Within that ceiling, maxJobsPerSearch (default 20, max 1000) sets the budget for each title/location pair; the run's total before de-duplication is roughly pairs × maxJobsPerSearch, and the actual saved total is smaller once jobs found by more than one search are removed. In company-restricted mode, maxJobs (default 20, max 1000) is the total across all listed companies instead. The Actor paginates the search endpoint in steps of 10 results — LinkedIn's real page size — and stops early if a page repeats the previous page's job IDs, which LinkedIn does once a query is exhausted.

Integrate LinkedIn Jobs Scraper and automate your workflow

LinkedIn Jobs Scraper works with any language or tool that can send an HTTP request, since it runs as a standard Apify Actor behind the Apify API.

REST API integration

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<YOUR_USERNAME>/linkedin-jobs-scraper-by-multiple-keywords-locations").call(run_input={
"jobTitles": ["Data Analyst", "Data Engineer"],
"searchLocations": ["Austin, Texas, United States", "Chicago, Illinois, United States"],
"maxJobsPerSearch": 50,
"titleExcludes": ["senior", "principal"],
})
for job in client.dataset(run["defaultDatasetId"]).iterate_items():
print(job["title"], job["companyName"], job["location"], job["salary"])

Works in Python, Node.js, Go, Ruby, cURL — any language that can make an HTTP request.

Automation platforms (n8n, Make, LangChain)

In n8n, the Apify node can start this Actor and pass through the same JSON input shown above, or an HTTP Request node can call the Apify run endpoint directly with your token. In Make, the Apify module runs the Actor and maps dataset rows into a Google Sheets, Airtable or CRM step — useful for a scheduled weekly hiring-signal pull by company. In a LangChain or similar agent framework, the Actor is invoked as a standard tool call over the Apify API; the JSON rows it returns need no parsing step before being passed into an LLM prompt or a vector store.

Scraping publicly accessible job postings is broadly treated as permissible where the data requires no login to view, and LinkedIn Jobs Scraper only reads LinkedIn's logged-out guest job pages — the same postings any anonymous visitor can see without an account.

Job listings, employer names and posting details are business and professional records, governed primarily by LinkedIn's terms of service and general database-rights principles around systematic reuse of a compiled dataset, not by personal-data regimes. The exception is the posterFullName and posterProfileUrl fields: when LinkedIn names an individual job poster, that is personal data, and storing or using it — particularly for outreach — can bring GDPR or CCPA into scope depending on your jurisdiction and use case.

Consult legal counsel for commercial use cases involving bulk data collection or any processing of the poster fields.

❓ Frequently asked questions

Does LinkedIn Jobs Scraper work without a LinkedIn account?

Yes. The Actor never logs in — it reads LinkedIn's public guest job search and job-detail pages, the same ones an anonymous visitor sees. The only credential you need is your Apify token.

How often is the scraped data updated?

Every run fetches live from LinkedIn at the time it runs. There is no cache — a run started now returns whatever LinkedIn's guest surfaces show at that moment, including postings published minutes earlier.

What happens if a search returns zero results or a job listing can't be parsed?

A search that returns no cards for a title/location pair contributes zero rows and logs a jobsFound: 0 entry in the per-search summary; the run continues with the remaining pairs. A job ID that is found but fails to fetch or parse (blocked response, timeout, unparseable page) is written as an uncharged accounting row with errorReason set to a code like throttled_999, http_403 or unparseable_page — it is never billed and never silently dropped.

Can I scrape private or login-gated LinkedIn job content?

No. Only job postings visible on LinkedIn's public guest surfaces are returned. Content that requires a logged-in session to view — anything behind LinkedIn's own account wall — is out of scope for this Actor.

How am I charged for using LinkedIn Jobs Scraper?

You're charged per successfully scraped job row (the row_result event). Accounting rows for jobs that could not be fetched or parsed — identifiable by a non-null errorReason — are pushed to the dataset for auditability but are not charged.

Does LinkedIn Jobs Scraper work for AI agent workflows and LLM pipelines?

Yes. It's callable as a standard HTTP endpoint through the Apify API, so any agent framework — LangChain, CrewAI, a custom tool definition, n8n — can invoke it and get back typed JSON with no parsing step.

How does LinkedIn Jobs Scraper handle LinkedIn's anti-bot system?

By default it runs with no proxy, since LinkedIn's guest job surfaces are reachable directly. LinkedIn's HTTP 999 response is a throttle rather than a block, and the Actor backs off and retries rather than treating it as a failure. If a request comes back blocked (an empty response or HTTP 403/429), the Actor escalates through Apify Proxy — datacenter first, then residential — automatically, if proxyConfiguration has proxy enabled.

How does LinkedIn Jobs Scraper compare to other LinkedIn scrapers?

Checked on the Apify Store on 2026-07-25, curious_coder/linkedin-jobs-scraper works from a pasted LinkedIn search URL and documents more employer-firmographic fields (employee count, company description); lntb/...multiple-titles-locations-in-one also runs a multi-title/multi-location search and documents apply-URL extraction; bebity/linkedin-jobs-scraper is single-query only. This Actor's difference is the matrix mechanics themselves — a documented cartesian title × location expansion with cross-search de-duplication, per-row search provenance, and a pre-fetch title screen that avoids paying for jobs it's going to discard anyway.

Does LinkedIn Jobs Scraper return data in a format LLMs can use directly?

Yes. Typed, normalized JSON with stable field names on every run — no HTML, no selectors. Pass a row directly into an LLM context window, index it into a vector store, or route it through an agent tool.

Can I use LinkedIn Jobs Scraper without managing proxies?

Yes, in the default configuration — LinkedIn's guest job surfaces don't require one. If you do see blocks in your region, enable proxyConfiguration and the Actor manages proxy selection and rotation on failure itself.

What happens when LinkedIn changes its structure or blocks the scraper?

The scraper is maintained, and the output schema is the stable contract — field names and types don't change on your end even when LinkedIn's page layout does. No numeric turnaround time is promised for any given fix.

Scraper NameWhat it extracts
LinkedIn Phone Number Scraper & Email FinderContact details for a LinkedIn profile URL — pairs with the posterProfileUrl this Actor returns
LinkedIn Company URL - Mass Profile FinderExpands a LinkedIn company URL into the people behind it — pairs with companyUrl
LinkedIn Post Comments Scraper With Commenter Profile DetailsLinkedIn post comments plus the commenter's profile details, for engagement rather than hiring data

💬 Your feedback

Found a bug, or need a field LinkedIn shows that this Actor doesn't extract yet? Open an issue on the Actor's Issues tab on Apify — reports with a sample search (job title, location) are the fastest to act on.