LinkedIn Jobs Scraper (No Cookies)
Pricing
from $0.25 / 1,000 jobs
LinkedIn Jobs Scraper (No Cookies)
Scrape public LinkedIn job postings by keyword and location without login or cookies: title, company, location, posting date, salary, plus optional full details (description, seniority, employment type, applicants, external apply link, recruiter).
Scrape public LinkedIn job postings by keyword and location, with no login, no cookies and no LinkedIn account. The scraper reads the same public "guest" job pages LinkedIn shows to signed-out visitors, over plain HTTP with no browser, so it is fast and cheap.
For every job you get the title, company with its link and logo, location, posting date, salary (when shown) and the job link. You can optionally add the full job details: description (text and HTML), seniority level, employment type, job function, industries, applicant count, the external apply link, the recruiter and the salary range as numbers.
Use cases
- Job boards and aggregators: keep a niche job board filled with fresh postings by keyword and location.
- Recruiting and sourcing: watch which companies are hiring for which roles, and how many people applied.
- Lead generation: companies posting jobs are spending money right now. Get the company names, LinkedIn pages, recruiters and career-site apply links.
- Market research: track demand for skills, salary ranges and remote/hybrid share over time.
Input example
{"keywords": ["data engineer", "analytics engineer"],"location": "United Kingdom","maxItems": 100,"datePosted": "past_week","jobType": ["full_time", "contract"],"experienceLevel": ["mid_senior"],"workplaceType": ["remote", "hybrid"],"easyApplyOnly": false,"sortBy": "recent","includeDetails": true}
Or paste searches from your browser, filters included:
{ "startUrls": ["https://www.linkedin.com/jobs/search/?keywords=react%20developer&location=Germany&f_WT=2&f_TPR=r604800"] }
An empty input ({}) searches "software engineer" in the United States and saves 50 jobs. It finishes in seconds.
Output example
{"type": "job","jobId": "4156770518","title": "Senior Software Engineer","companyName": "Example Co","companyUrl": "https://www.linkedin.com/company/example-co","companyLogo": "https://media.licdn.com/dms/image/v2/…/company-logo_100_100/0/1?…","location": "San Francisco, CA","postedAt": "2026-10-27","postedTimeAgo": "2 days ago","salary": "$117,000.00/yr - $234,000.00/yr","benefits": "Actively Hiring","isEasyApply": false,"url": "https://www.linkedin.com/jobs/view/4156770518","keyword": "software engineer","searchLocation": "United States","scrapedAt": "2026-10-29T07:56:46.080Z","descriptionText": "About the role\n\nWe are hiring a Senior Software Engineer to …\n• 5+ years of TypeScript\n• Experience with distributed systems","descriptionHtml": "<strong>About the role</strong><br><br>We are hiring …","seniorityLevel": "Mid-Senior level","employmentType": "Full-time","jobFunction": "Engineering and Information Technology","industries": "Software Development","applicantsCount": 200,"applicantsText": "Over 200 applicants","applyUrl": "https://careers.example.com/jobs/4156770518?source=linkedin","recruiterName": "Jordan Example","recruiterTitle": "Technical Recruiter at Example Co","salaryMin": 117000,"salaryMax": 234000,"salaryCurrency": "USD","salaryPeriod": "year"}
All values above are invented. The fields from descriptionText down appear only with includeDetails: true.
Details on some fields:
postedAtis the posting date LinkedIn gives (YYYY-MM-DD).applicantsCountis a number:- "Over 200 applicants" gives
200. - "Be among the first 25 applicants" gives
0and keeps the original text inapplicantsText.
- "Over 200 applicants" gives
isEasyApplyistruefor LinkedIn Easy Apply jobs andfalsefor jobs that apply on the company's own site.applyUrl: LinkedIn hides the external application link from logged-out visitors, so this is usuallynull. Useurlto open the job.recruiterName/recruiterTitleare filled only when LinkedIn shows the "Meet the hiring team" block publicly (roughly 10–15% of jobs).salaryis filled only when the employer publishes it;salaryMin/salaryMax/salaryCurrency/salaryPeriodare parsed from it (e.g.SGD 4,000.00/mo - SGD 5,200.00/mo).detailsErrorappears when the details could not be read, for example when a job was removed. The job is still saved with its card data and charged as ajobonly.
The run's summary is in the key-value store under OUTPUT:
{ "keywords": ["software engineer"], "location": "United States", "jobsScraped": 50, "detailsFetched": 0, "blockedRequests": 0, "usedResidential": false, "perSearch": [ … ] }
Pricing
Pay per event:
jobis charged once per job saved.job-detailsis charged on top for each job saved with its full details (includeDetails).
The run stops cleanly when your maximum cost per run is reached.
| Plan | job per 1,000 | job-details per 1,000 (extra) |
|---|---|---|
| Free | $0.35 | $0.55 |
| Bronze | $0.32 | $0.50 |
| Silver | $0.28 | $0.45 |
| Gold+ | $0.25 | $0.40 |
How it works
- Search pages. For each keyword (or start URL) the scraper reads LinkedIn's public guest search results, about 10 jobs per page, and pages on until it has
maxItemsjobs or a page comes back empty. LinkedIn stops after about 1,000 results per search. - Details (optional). For each job it reads the public job page.
- Duplicates are removed by job ID across all keywords.
- Blocking:
- A 429, a 999 (LinkedIn's block code), a 401/403, a redirect to the sign-in wall or an empty response counts as blocked. The scraper drops that session, waits a random, growing delay and retries, up to 5 retries.
- After 3 blocks in a row on datacenter proxy, the rest of the run uses RESIDENTIAL proxy, and the summary says
usedResidential: true. - Each session gets a realistic desktop browser identity and language.
- Run timeout. About 45 seconds before the run's timeout, the scraper stops, saves everything it has (including jobs still waiting for details, with their card data) and exits successfully.
FAQ
Do I need a LinkedIn account, login or cookies? No. The scraper only reads pages LinkedIn shows publicly to signed-out visitors, and it never sends cookies.
Why fewer jobs than LinkedIn's result count? LinkedIn shows at most about 1,000 jobs per search to signed-out visitors, and its counts are estimates. Use narrower keywords, locations or filters (date posted, job type, experience level, workplace type) to reach more of them.
Why is the salary often empty?
Many employers don't publish a salary. When LinkedIn shows one, it is in salary (and with details, as salaryMin, salaryMax, salaryCurrency and salaryPeriod).
Can I use my own LinkedIn search?
Yes. Paste the URL from your browser into startUrls. Its filters are kept. If you leave Keywords at the default, only your URLs are scraped.
What if LinkedIn blocks the run?
The scraper retries on new sessions and switches to residential proxy by itself. If LinkedIn still blocks every single request, the run fails with a clear message instead of finishing "successfully" with nothing. If you see many blockedRequests in the summary, run fewer keywords at once or use residential proxy from the start.
Is the description complete?
With includeDetails, descriptionText and descriptionHtml hold the full description LinkedIn shows to signed-out visitors.
Development
npm installnpm test # unit tests on synthetic fixtures (+ live-capture tests when captured)npm run mock-server # offline LinkedIn guest mock on :4596 (scenarios in test/mock-server.ts)LI_BASE_URL=http://127.0.0.1:4596 npm start # end-to-end against the mock (input: {"proxyConfiguration":{"useApifyProxy":false}})npm run capture-fixtures # save real LinkedIn guest responses to test/fixtures/live/ (needs network)npm run fixtures # regenerate the synthetic fixtures
RESIDENTIAL_PROXY_URL (development only) replaces Apify RESIDENTIAL proxy with your own proxy URL when the run switches.