LinkedIn Jobs Scraper
Pricing
from $0.80 / 1,000 results
LinkedIn Jobs Scraper
Scrape LinkedIn job listings by keyword, location or saved search URL, with no login and no account. Every row carries title, company_name, location, salary_min, salary_max, applicants_count, posted_at and full company detail. Export JSON, CSV or Excel.
Pricing
from $0.80 / 1,000 results
Rating
0.0
(0)
Developer
bootforge
Maintained by CommunityActor stats
0
Bookmarked
35
Total users
11
Monthly active users
a day ago
Last modified
Categories
Share
LinkedIn Jobs Scraper extracts job listings from LinkedIn by keyword, location or a saved search URL — no login and no LinkedIn account. Every row carries title, company, salary, applicant count, the full description, the job poster and complete company detail.
What you get
One flat dataset row per job, 33 fields wide. Export as JSON, CSV or Excel.
{"job_id": "4381014743","title": "Senior Python Developer","company_name": "hackajob","company_website": "https://www.hackajob.com","company_size": "51-200 employees","company_industry": "Software Development","location": "Boston, MA","employment_type": "Full-time","salary_min": 135000.0,"salary_max": 155000.0,"salary_currency": "USD","applicants_count": 25,"posted_at": "2026-03-29T00:00:00+00:00"}
Rows also carry url, apply_url and easy_apply, the listing's own seniority_level, job_function and industries, salary_period alongside the salary figures, description_text and description_html, the company's company_url, company_type, company_headquarters, company_founded, company_description and company_logo_url, and the poster's poster_name, poster_title and poster_profile_url. Empty fields are missing source data, not a failure: LinkedIn shows salary only where the employer published it, workplace_type only where the employer stated it, and apply_url only where applying does not go through a sign-in.
What it costs
| Event | Price |
|---|---|
result (apify-default-dataset-item) | $0.0008 |
Actor Start (apify-actor-start) | $0.01 |
You pay per job, not per minute: $0.0008 a result, so 1,000 jobs is about $0.80 and 10,000 about $8.00. Company detail, salary parsing and poster information are inside that price rather than extra events, and so is the residential proxy. The $0.01 start fee is charged once per run, per GB of memory.
Input
| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
search_queries | array | no | — | Job-title keywords to search on LinkedIn, one per entry. Each keyword is searched separately and the results are merged and de-duplicated by job ID. Examples: python developer, data scientist, product manager. Provide at least one of search_queries or search_urls; leave empty to collect only the URLs you paste. |
search_urls | array | no | — | Ready-made LinkedIn job-search URLs, one per entry: paste a saved search, or set the filters you want on LinkedIn and paste the resulting address. Provide at least one of search_urls or search_queries; leave empty to search by keyword only. |
location | string | no | — | Where to search: a city, a region, a country, or Remote. Examples: New York, London, UK, United States. Leave empty to search worldwide. A geo_id, when you set one, overrides this text. |
geo_id | string | no | — | LinkedIn's own numeric ID for a place, for exact targeting; it overrides the location text. Examples: 103644278 is the United States, 102095887 is California. Find one by running the search on LinkedIn and copying the geoId value out of the address bar. Leave empty unless a place name is too ambiguous to match. |
job_type | string | no | "" | Employment type a listing must advertise. Values: full-time, part-time, contract, temporary, volunteer, internship. Leave empty for any type. |
experience_level | string | no | "" | Seniority the listing asks for. Values: internship, entry, associate, mid-senior, director, executive. Leave empty for any level. |
workplace_type | string | no | "" | Where the work happens. Values: on-site at the employer's premises, remote fully remote, hybrid part office part home. Leave empty for any arrangement. |
date_posted | string | no | "" | How recent a posting must be. Values: 24h the last day, week the last seven days, month the last thirty days. Leave empty for any date. Pair 24h with a daily schedule to collect only what is new. |
salary_range | string | no | "" | Lowest yearly pay in US dollars a listing must advertise. Values: 40k+, 60k+, 80k+, 100k+, 120k+. Leave empty for any salary, which also keeps the many listings that publish no pay at all. |
sort_by | string | no | "relevance" | Order the results come back in. Values: relevance best match first, date newest first. Default relevance. Pair date with a small max_results to take only the freshest postings. |
enrich_company | boolean | no | true | Also collect the employer's own LinkedIn page for every job, adding company_website, company_size, company_industry, company_type, company_headquarters, company_founded and the logo. Default true. Set it to false for a quicker listing-only run; the per-result price is the same with it on or off. |
enrich_poster | boolean | no | true | Also collect the person who posted the job, as poster_name, poster_title and poster_profile_url, wherever LinkedIn publishes them. Default true. Set it to false when the listing and the company are all you need. |
auto_split | boolean | no | true | LinkedIn stops a single search at about 1000 results. Leave this on and each search is repeated split across date, job type, experience level and workplace, so a broad search returns far more than the cap, de-duplicated by job ID. Default true. |
split_by | string | no | "" | Which dimension a split search is divided along. Values: date_posted, job_type, workplace_type. Leave empty to have auto_split pick the dimension for you. It has no effect while auto_split is off. |
max_results | integer | no | 10 | Most job listings returned across every search combined. Default 10, minimum 1, maximum 10000. The default is a quick, cheap first run — raise it for real collection. Above about 100 results also raise the run timeout under Run options: 100 results takes roughly two minutes and 500 roughly fifteen. |
max_concurrency | integer | no | 10 | How many requests may be in flight at the same time. Default 10, minimum 1, maximum 30. A higher number finishes a large run sooner. |
max_requests_per_minute | integer | no | 120 | Ceiling on how many requests a run may send each minute. Default 120, minimum 10, maximum 120. Lowering it stretches a run out in proportion, and a low ceiling is the usual reason a large run reaches its timeout. |
cache_provider | string | no | "memory" | Where company and poster detail is kept during a run, so the same company is not looked up twice. Values: memory for the current run only, file to keep it on disk when you run the package yourself, apify to keep it across runs in the key-value store. Default memory. |
request_delay | integer | no | 0 | Seconds to wait between requests, to spread a long run out over time. Default 0, minimum 0, which runs at full speed inside the ceiling set by max_requests_per_minute. |
proxyUrls | array | no | — | Leave empty: the run uses the residential proxy this actor ships with, included in the price of the run. To route the run through your own provider instead, add one gateway URL per entry, for example http://user:pass@host:port — works with any provider that issues URLs (DataImpulse, Bright Data, Oxylabs, Smartproxy, or your own). When set, these are used exactly as entered and nothing else is. |
How to run it
- Open the actor on Apify Console.
- Enter one or more job-title keywords, or paste saved LinkedIn search URLs.
- Set the location and any filters, then Run. Export JSON, CSV or Excel from the dataset.
{"search_queries": ["python developer"],"location": "United States","job_type": "full-time","date_posted": "week","sort_by": "date","enrich_company": true,"max_results": 100}
Minimal input:
{"search_queries": ["python developer"]}
Available as the MCP tool herus13--linkedin-jobs-scraper on mcp.apify.com and through the Apify API; send the same JSON.
Why this scraper
- No login, no cookies — nothing to authenticate, no account to put at risk, no
li_attoken to keep alive. - The company dataset comes free — website, employee count, industry, type, headquarters, founding year and logo arrive on every job row, at the same per-result price.
- Past the 1,000-result cap — LinkedIn truncates a single search at about a thousand results;
auto_splitrepeats the search across date, job type, experience level and workplace and de-duplicates, so a broad query returns far more. - Salary read from two places — the search card and the detail page's compensation section, in yearly, monthly or hourly form, with currency and period kept separate.
- Partial results are never lost — rows are written to the dataset as they are collected, so a run that hits its timeout still hands you everything gathered up to that point.
- Nothing to set up — no account, no cookies, no proxy configuration; a residential proxy is included in the price of the run.
Use cases
- Recruiting pipelines — 33 flat fields per job, poster details and full company enrichment mean a job row already reads as a qualified lead rather than something to enrich in a second pass.
- Competitor hiring intelligence — Applicant counts show which roles are contested and which are struggling to fill; with company size and industry beside them, that is a read on where a rival is investing.
- Job-board feeds — Keywords, a location or a saved LinkedIn search URL all work as input, so an existing search becomes a feed without rebuilding the query.
- Salary benchmarking — Salary next to location, experience level and workplace type supports genuine like-for-like comparison instead of one blended national figure.
- Market mapping — Industry, company size and headquarters on every row let a whole hiring market roll up by sector or by region.
FAQ
Do I need a LinkedIn account or login? No. The actor reads only publicly visible listing and company pages, so there is no account, no cookie and no li_at token to supply, and nothing of yours to get flagged.
How many jobs can I collect? Effectively as many as you want. LinkedIn stops a single search at about 1,000 results, but auto_split (on by default) repeats each search split across date, job type, experience level and workplace, de-duplicated by job ID.
Why are some salary or company fields empty? LinkedIn shows salary only when the employer publishes it — roughly 40 to 60% of US postings and fewer elsewhere — and not every company keeps a full page. Missing values come back as null rather than fabricated.
My run timed out. What should I change? Raise the run timeout under Run options before starting: about 100 results needs a couple of minutes, 500 around fifteen. Everything collected before a timeout is already in the dataset.
Is a proxy included? A residential proxy is included in the price of the run. To use your own, paste gateway URLs into Your own proxy URLs. Scraping at volume? Your own DataImpulse account is cheaper per GB.
Is scraping LinkedIn jobs legal? This actor collects only publicly available job and company data. You are responsible for complying with LinkedIn's terms and applicable laws. Do not collect personal data without a lawful basis, and do not use the output in ways that breach privacy or anti-discrimination rules.
Related actors
Building a job-market pipeline? Pair this actor with:
- LinkedIn Profile Scraper — LinkedIn profiles with full experience history and optional contact enrichment.
- Indeed Job Scraper — Indeed listings with structured salary and map coordinates across 59 countries.
- JobStreet & JobsDB Scraper — job listings across Malaysia, Singapore, the Philippines, Indonesia, Thailand and Hong Kong.
- levels.fyi Salary Scraper — verified tech compensation by company, level and location.