LinkedIn Jobs Scraper (No Cookies) avatar

LinkedIn Jobs Scraper (No Cookies)

Pricing

from $0.25 / 1,000 jobs

Go to Apify Store
LinkedIn Jobs Scraper (No Cookies)

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).

Pricing

from $0.25 / 1,000 jobs

Rating

0.0

(0)

Developer

Zee Lex

Zee Lex

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Categories

Share

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:

  • postedAt is the posting date LinkedIn gives (YYYY-MM-DD).
  • applicantsCount is a number:
    • "Over 200 applicants" gives 200.
    • "Be among the first 25 applicants" gives 0 and keeps the original text in applicantsText.
  • isEasyApply is true for LinkedIn Easy Apply jobs and false for jobs that apply on the company's own site.
  • applyUrl: LinkedIn hides the external application link from logged-out visitors, so this is usually null. Use url to open the job.
  • recruiterName / recruiterTitle are filled only when LinkedIn shows the "Meet the hiring team" block publicly (roughly 10–15% of jobs).
  • salary is filled only when the employer publishes it; salaryMin/salaryMax/salaryCurrency/salaryPeriod are parsed from it (e.g. SGD 4,000.00/mo - SGD 5,200.00/mo).
  • detailsError appears 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 a job only.

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:

  • job is charged once per job saved.
  • job-details is charged on top for each job saved with its full details (includeDetails).

The run stops cleanly when your maximum cost per run is reached.

Planjob per 1,000job-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

  1. 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 maxItems jobs or a page comes back empty. LinkedIn stops after about 1,000 results per search.
  2. Details (optional). For each job it reads the public job page.
  3. Duplicates are removed by job ID across all keywords.
  4. 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.
  5. 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 install
npm 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.