LinkedIn Jobs Scraper avatar

LinkedIn Jobs Scraper

Pricing

from $1.00 / 1,000 jobs

Go to Apify Store
LinkedIn Jobs Scraper

LinkedIn Jobs Scraper

Scrape LinkedIn jobs from search URLs or filters. Get title, salary, full description, seniority, applicants, apply link, recruiter and company data (website, size, industry). Split searches by city to get past the 1000-job cap. No login or cookies needed. Export to JSON, CSV or Excel.

Pricing

from $1.00 / 1,000 jobs

Rating

0.0

(0)

Developer

Brisk Pebble

Brisk Pebble

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Categories

Share

Scrape public LinkedIn job listings, with no login and no cookies. For every job you get the full description, salary, seniority, employment type, applicant count, apply URL, the recruiter who posted it, and a company profile (website, size, industry, headquarters, followers).

Paste LinkedIn job search URLs, or fill in a few filters (keywords, location, date posted, companies). To get past LinkedIn's limit of about 1000 jobs per search, you can split a search across a country's cities.

What can this LinkedIn Jobs Scraper do?

  • Search by URL or by filters. Paste any public linkedin.com/jobs/search URL, single job URLs (/jobs/view/...), or use keywords, location, geoId, distance, date posted, company IDs, Easy Apply and "under 10 applicants".
  • Full job details. Description (HTML and plain text), seniority level, employment type, job function, industries, applicant count, salary, external apply URL or Easy Apply, and whether the job is closed.
  • Job poster. Name, headline, photo and profile URL of the recruiter, when LinkedIn shows them.
  • Company enrichment. Website, employee count, size range, industry, headquarters, postal address, organization type, founding year, specialties, followers, slogan and description. Each company is fetched once per run, however many jobs it has.
  • Works with LinkedIn's AI job search. LinkedIn's public search now ignores classic filters like job type, experience, workplace type and salary. This Actor rewrites them into keywords (e.g. f_WT=2 becomes "remote"), so old search URLs still return relevant jobs.
  • Get past the 1000 results cap. Split a search across the major cities of 30+ countries, or across your own list of locations. Duplicate jobs are removed automatically.
  • Pay only for what you want. Title and company exclusions are applied before job pages are opened. You can also turn off details for a fast run that returns search card data only.
  • Reliable at scale. Uses residential proxies, session rotation on blocks (HTTP 429/999, auth walls), automatic retries and persisted state, so migrated runs resume without duplicates. If a job page can't be loaded, the job is still saved with its search card data.

How to scrape LinkedIn jobs

  1. Open linkedin.com/jobs/search in an incognito window. The public search can differ from the logged-in one.
  2. Search with the filters you want and copy the URL from the address bar.
  3. Paste it into LinkedIn job search URLs. Alternatively, leave URLs empty and fill in Search filters.
  4. Set Max jobs per search and click Start.
  5. Download the results as JSON, CSV, Excel or HTML, or get them through the API.

Input example

{
"keywords": "data engineer",
"location": "United States",
"datePosted": "pastWeek",
"workplaceTypes": ["2"],
"scrapeCompany": true,
"limitPerSource": 200,
"titleExcludeKeywords": ["intern"],
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

The same search, using a URL:

{
"urls": ["https://www.linkedin.com/jobs/search/?keywords=data%20engineer&location=United%20States&f_TPR=r604800&f_WT=2"],
"limitPerSource": 200
}

Getting every Python job in Germany, past the 1000 cap:

{
"keywords": "python",
"splitByLocation": true,
"splitCountry": "DE"
}

Input fields

FieldDescription
urlsLinkedIn job search URLs or job URLs. When set, the search filters are ignored.
keywords, location, geoId, distanceSearch filters used when no URLs are given.
datePostedanyTime, pastHour, past24Hours, pastWeek, pastMonth.
companyIdsLinkedIn numeric company IDs (f_C= in search URLs).
under10Applicants, easyApplyBoolean URL filters supported by the public search.
jobTypes, experienceLevels, workplaceTypes, minSalary, sortByClassic filters. Rewritten into keywords when autoConvertToAiSearch is on.
autoConvertToAiSearchRewrite unsupported classic filters into keywords (default true).
scrapeJobDetailsOpen every job page (default true). Turn off for a fast run with search card data only.
scrapeCompanyAdd company details (default true).
limitPerSourceMax jobs per search. Empty means everything LinkedIn returns, up to about 1000.
maxItemsMax jobs in total across all searches.
splitByLocation, splitCountry, splitLocationsRun each search once per city to get past the 1000 cap.
titleExcludeKeywords, companyExcludeNamesSkip unwanted jobs before paying for their details.
proxyConfigurationResidential proxy recommended (default).
maxConcurrency, maxRequestRetriesPerformance tuning.

Output example

{
"id": "4012345678",
"trackingId": "TrackAAA==",
"refId": "RefAAA==",
"link": "https://www.linkedin.com/jobs/view/senior-python-developer-at-acme-4012345678",
"title": "Senior Python Developer",
"companyName": "Acme Corp",
"companyLinkedinUrl": "https://www.linkedin.com/company/acme",
"companyLogo": "https://media.licdn.com/dms/image/acme-logo.png",
"location": "New York, NY",
"salary": "$140,000.00/yr - $180,000.00/yr",
"postedAt": "2026-10-18",
"postedTimeAgo": "1 day ago",
"benefits": ["Actively Hiring"],
"applicantsCount": "Over 200 applicants",
"applyUrl": "https://careers.acme.com/jobs/123",
"applyType": "EXTERNAL",
"isClosed": false,
"descriptionHtml": "<strong>About us</strong><br>…",
"descriptionText": "About us\n\nAcme builds rockets.\n\n• 5+ years of Python",
"seniorityLevel": "Mid-Senior level",
"employmentType": "Full-time",
"jobFunction": "Engineering and Information Technology",
"industries": "Software Development",
"jobPosterName": "Jane Doe",
"jobPosterTitle": "Technical Recruiter at Acme",
"jobPosterPhoto": "https://media.licdn.com/dms/image/jane.jpg",
"jobPosterProfileUrl": "https://www.linkedin.com/in/janedoe",
"companyDescription": "Acme builds rockets for everyone.",
"companySlogan": "Building the future",
"companyWebsite": "https://www.acme.com",
"companyEmployeesCount": 5230,
"companySize": "1,001-5,000 employees",
"companyIndustry": "Software Development",
"companyHeadquarters": "New York, NY",
"companyType": "Public Company",
"companyFounded": "2004",
"companySpecialties": "Rockets, Anvils",
"companyFollowers": 120345,
"companyAddress": { "type": "PostalAddress", "streetAddress": "1 Main St", "addressLocality": "New York", "addressRegion": "NY", "postalCode": "10001", "addressCountry": "US" },
"inputUrl": "https://www.linkedin.com/jobs/search/?keywords=python",
"scrapedAt": "2026-10-19T12:00:00.000Z"
}

Fields LinkedIn doesn't show for a job are null. A detailError field appears only when the job page couldn't be loaded and the item holds search card data only.

The dataset has three views: Overview, Job details and Companies.

How much does it cost?

The Actor uses lightweight HTTP requests (no browser), so 512 MB of memory is enough. Each job costs one request for its page. Each new company costs one more request, and that result is reused for all of the company's jobs. Turning off Scrape job details cuts the cost to about one request per 10 jobs.

Tips

  • Use residential proxies. LinkedIn rate-limits datacenter IPs heavily.
  • Need more than ~1000 jobs? Turn on Split search by city locations, or split by date (e.g. run past24Hours daily).
  • Daily monitoring. Schedule the Actor with datePosted: "past24Hours" and combine it with an integration (Google Sheets, Slack, webhooks).
  • Missing jobs? The public search shows fewer results than a logged-in session, and some filters behave differently. Check your URL in an incognito window.

This Actor only reads data that LinkedIn shows publicly to logged-out visitors. It doesn't log in, and it doesn't access private profiles. Personal data (such as job poster names) is protected by regulations like GDPR. Only scrape personal data when you have a legitimate reason, and consult a lawyer if you're unsure.

Development

npm install
npm test # unit tests + end-to-end test against a local mock of LinkedIn
npm run build # compile TypeScript to dist/
apify run # run locally with the input in storage/key_value_stores/default/INPUT.json
apify push # deploy to the Apify platform

Project layout:

.actor/ Actor definition: actor.json, input, dataset and output schemas, Dockerfile
src/main.ts Entry point: input, proxy, state and crawler setup
src/routes.ts SEARCH (pagination, de-duplication, limits) and DETAIL (job + company) handlers
src/parsers.ts Cheerio parsers for search cards, job pages and company pages
src/urls.ts Search URL parsing/building and AI-search filter conversion
src/sources.ts Turns the input into searches, including split by location
src/company.ts Per-run company cache
src/cities.ts City lists used for split by location
test/ Vitest unit tests, HTML fixtures and an end-to-end test
assets/icon/ Actor icon: SVG source and 1024/512/256 px PNGs (upload icon-1024.png in Console)