LinkedIn Jobs Scraper avatar

LinkedIn Jobs Scraper

Pricing

from $0.34 / 1,000 job-details

Go to Apify Store
LinkedIn Jobs Scraper

LinkedIn Jobs Scraper

Scrape LinkedIn jobs from keywords and locations or search URLs, no login needed. Get full descriptions, seniority, employment type, industries, declared salary, real posting dates, applicant counts, recruiter cards and company profiles. Schedule it to return only new jobs. $0.60 per 1,000 jobs.

Pricing

from $0.34 / 1,000 job-details

Rating

0.0

(0)

Developer

BonCross API

BonCross API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

What is LinkedIn Jobs Scraper?

LinkedIn Jobs Scraper gets you LinkedIn job postings with the employer's company profile attached, for one price: $0.60 per 1,000 jobs on the Free plan, company data included. You type keywords and a location, or paste a LinkedIn job search URL. You never sign in to LinkedIn, and there's no API key to arrange.

Four reasons to choose it:

  • The company profile costs nothing extra. Switch on "Scrape company details" and each job gains industry, size, headquarters, website and follower count. A job with company data is billed the same $0.0006 as a job without.
  • You get the real posting date. LinkedIn's page says "1 day ago". You get the date, and you can narrow a search to the last N hours, which is what a monitor that runs every six hours needs.
  • Cheap filters run first. Title and company filters are applied to the search results before any posting is opened. A job they drop costs $0.00005, a twelfth of the full price.
  • It's quick. 1,100 jobs with details took 2 minutes 14 seconds across six searches on 5 October 2026, about 490 a minute.

BonCross Verified means we tested this actor against the live site before release and kept the record:

  • 41 of 41 live checks on its inputs and filters passed on 6 October 2026
  • 10 searches run on 7 October 2026 across Manchester, Berlin, Tokyo, Austin and São Paulo: 100 jobs, none empty
  • 6 of 6 sampled adverts matched LinkedIn's own pages, one read by hand
  • Charges checked against the 100 rows

What else it does:

  • Extract job title, company, location, the full description (text and HTML) and seniority level
  • Read the applicant count as a number, and filter on it
  • Pick up the recruiter card where LinkedIn shows one
  • Collect declared pay as minimum, maximum, period and currency where the employer states it
  • Search by company name. You don't need LinkedIn's numeric company ids
  • Search several locations in one run, which is how you get past LinkedIn's ceiling of about 1,000 results per search
  • Return only the postings added since your last run
  • Drop staffing agencies and see direct employers only

People point it at a job board or aggregator that needs fresh postings, at a watchlist of named companies, or at a market they want to check for new roles every few hours. It also feeds pay benchmarking (where LinkedIn shows pay) and CRM enrichment with company size, industry and headquarters.

What data can you extract from LinkedIn jobs?

💼 Job title🏢 Company name and LinkedIn company URL
📍 Location📅 Posting date (real) and the posted-ago text
📝 Full description, text and HTMLSeniority level
Employment typeIndustries
Job poster profileBenefits tags, where shown
👥 Applicant countRecruiter name, title and profile, where shown
Company logo🌐 Company website
Company size and employee countCompany type and headquarters, with street, postcode and country code
Company specialties🔗 Job URL and job id
Company follower countCompany tagline and URL slug
Company office addressesEasy Apply flag (isDirectApply)
💷 Declared pay, where the employer states itLinkedIn company id
Search keyword and search URLScrape timestamp

How to scrape LinkedIn jobs

There's no code to write. You fill in a form and download a spreadsheet.

  1. Create a free Apify account and open LinkedIn Jobs Scraper.
  2. Add your keywords and a location. If you've already built the search on LinkedIn, paste its URL into Start URLs.
  3. Pick a date window. The default is the past 24 hours.
  4. Add title or company filters if you want to keep the bill down, then press Start.
  5. Download the jobs as Excel, CSV, JSON, XML or HTML when the run finishes.

⬇️ Input

Keywords and a location are enough. So is a LinkedIn search URL on its own.

Each posting is opened for its full advert unless you switch "Fetch job details" off. Company details are off until you ask for them, and add one lookup per company the run hasn't seen before.

You have two limits to work with. "Max results per search" (10 to 1,000, default 100) applies to each keyword, location or URL separately, so ten searches at 50 each can return 500. "Maximum results for the whole run" sits over all of them. Leave it at 0 for no cap. Past it, nothing is returned or charged.

Recent jobs for two keywords in London

{
"keywords": ["paralegal", "compliance analyst"],
"location": "London, United Kingdom",
"datePosted": "past24h",
"maxResultsPerSearch": 200
}

A six-hourly monitor across two cities, only new postings

{
"keywords": ["administrator"],
"locations": ["London, United Kingdom", "Manchester, England, United Kingdom"],
"postedWithinHours": 6,
"dedupStoreName": "linkedin-admin-seen",
"titleExclude": ["recruitment consultant", "sales"],
"scrapeCompany": true
}

Entry-level roles with few applicants, agencies excluded

{
"keywords": ["junior data analyst"],
"location": "United Kingdom",
"datePosted": "pastWeek",
"experienceLevels": ["entry"],
"seniorityLevelsFilter": ["Entry level", "Associate"],
"maxApplicants": 25,
"scrapeCompany": true,
"excludeStaffingAgencies": true
}

Jobs at named companies

Give the names and the run finds each company's LinkedIn id for you, then reports what each name matched. Company names aren't unique, so the log lists the runners-up as well.

{
"keywords": ["engineer"],
"location": "United Kingdom",
"companyNames": ["Monzo", "Wise"]
}

A pasted LinkedIn search URL

{
"startUrls": [
{ "url": "https://www.linkedin.com/jobs/search/?keywords=product%20manager&location=Berlin&f_TPR=r86400&f_EA=true" }
],
"maxResultsPerSearch": 100
}
FieldNotes
keywords, location, locations, geoId, distanceSearch terms and where to search. Several locations run as several searches.
startUrlsLinkedIn job search URLs, including older ones with legacy filter parameters.
datePosted, postedWithinHoursDate window, down to the hour.
sortByMost recent first. LinkedIn no longer sorts the public job search, so this is applied to the collected results: it orders what the run fetched, it cannot change which jobs LinkedIn selects.
experienceLevels, jobTypes, workplaceTypesCodes such as entry, part-time, remote. Folded into the search terms. This steers the search strongly but is not exact on its own, and it narrows the pool. Pair with the matching post-fetch filter below for exact results.
under10Applicants, easyApply, companyIds, companyNamesFilters LinkedIn still applies to the search itself. companyNames takes plain names ("Monzo") and resolves each to the id the filter needs, so you never have to look one up.
titleInclude, titleExclude, companyExcludeFree filters applied before any detail is fetched.
seniorityLevelsFilter, employmentTypesFilter, maxApplicants, minAnnualSalary, descriptionInclude, descriptionExclude, excludeStaffingAgenciesFilters applied after the detail is fetched, using LinkedIn's own labels. employmentTypesFilter and seniorityLevelsFilter are the exact versions of job type and experience level: set jobTypes: ["part-time"] with employmentTypesFilter: ["Part-time"] and every returned row is part-time.
fetchDetails, fetchFullJobPage, scrapeCompany, companyCacheDaysWhether to open each posting (full advert, criteria and declared pay), whether to read the full job page instead of the short advert (same columns, a real seniority level on far more jobs, about 45% slower), whether to enrich the company, and how long to cache company records.
maxResultsPerSearch (default 100, 10 to 1,000), maxItems, maxNewJobs, dedupStoreNameThe per-target cap, the run-wide cap, a cap on jobs returned, and the only-new store. maxItems and maxNewJobs default to 0, which means no limit.
maxConcurrency, delayMsParallel requests (1 to 10, default 8) and an optional extra pause before each request (default 0; the run already keeps to a rate measured safe for LinkedIn).

For developers

  • maxResultsPerSearch is the per-search limit and maxItems the run-wide one. maxItems and maxNewJobs default to 0, meaning no limit.
  • titleInclude, titleExclude and companyExclude run on the search results, before any posting is opened. A job they drop is billed job-scanned only.
  • The seniority, employment-type, applicant, salary, description and staffing-agency filters need the posting first. A posting that was opened is billed as a detail even when one of them then drops the job.
  • dedupStoreName names the store that remembers which jobs you've had. Later runs return only unseen postings, and the ones already seen cost the scan rate. maxNewJobs caps how many a run returns.
  • companyCacheDays (default 30) is how long a company record is reused before it's fetched again.
  • fetchFullJobPage reads the full job page in place of the short advert. The columns are the same, the seniority level is filled on far more jobs, and the run is about 45% slower.
  • maxConcurrency (default 8, from 1 to 10) is the number of requests in flight. delayMs (default 0) adds a pause before each one. The run already keeps to a rate measured safe for LinkedIn, and we'd leave both alone.
  • Jobs are written as they're read. Stop a run early and you keep what it collected.
  • A posting that can't be read after retries is returned with its listing fields and a detailError, billed as job-listed.

⬆️ Output

One record per job. The Output tab shows them as a labelled table, or as JSON if you prefer.

{
"id": "4462959761",
"url": "https://uk.linkedin.com/jobs/view/data-analyst-music-at-handle-recruitment-4462959761",
"title": "Data Analyst - music",
"company": "Handle Recruitment",
"companyUrl": "https://uk.linkedin.com/company/handle-recruitment",
"companySlug": "handle-recruitment",
"location": "London, England, United Kingdom",
"postedAt": "2026-09-07",
"closingAt": null,
"postedText": "6 days ago",
"benefits": [
"Actively Hiring"
],
"companyLogo": "https://media.licdn.com/dms/image/v2/D4E0BAQElJwj0RgST6A/company-logo_100_100/B4EZ1Df3q3HkAQ-/0/1774953921569/handle_recruitment_logo?e=2147483647&v=beta&t=ICdY7XWN2mVtJ-vArq8TMcqIC7bzPuO8NvuKIu78Mag",
"searchKeywords": "data analyst",
"searchUrl": "https://www.linkedin.com/jobs/search/?keywords=data+analyst&location=London&f_TPR=r604800&sortBy=DD",
"descriptionHtml": "<p>…</p>",
"description": "An exciting record label who are looking for a commercially minded Data Analyst to join their London team.\n\n This is a great opportunity for someone with 3-4 ye…",
"seniorityLevel": "Mid-Senior level",
"employmentType": "Full-time",
"industries": "Accounting",
"salaryText": null,
"salaryMin": null,
"salaryMax": null,
"salaryPeriod": null,
"salaryCurrency": null,
"applicantsText": "45 applicants",
"jobPosterProfileUrl": "https://uk.linkedin.com/in/example-recruiter",
"jobPosterName": "Alex Example",
"jobPosterTitle": "Recruitment Director",
"jobPosterPhoto": "https://media.licdn.com/dms/image/…/profile-displayphoto-scale_400_400/…",
"applicantsCount": 45,
"isDirectApply": true,
"companyDescription": "Handle Recruitment has been supporting the creative industries since 1978, building our reputation in music before expanding across film, TV, entertainment, fas…",
"companyWebsite": "http://www.handle.co.uk",
"companyIndustry": "Staffing and Recruiting",
"companySize": "51-200 employees",
"companyHeadquarters": "London",
"companyType": "Privately Held",
"companyFounded": "1978",
"companySpecialties": ["Digital Recruitment", "Sales and Marketing Recruitment", "Office Support Recruitment", "Legal Recruitment", "…"],
"companyId": "1234567",
"companyEmployeesCount": 56,
"companySlogan": "We've been supporting the UK's Creative Industries since 1978.",
"companyFollowers": 295258,
"companyLocations": [
"Ink Rooms, 25-37 Easton Street London, WC1X 0DS, GB"
],
"scrapedAt": "2026-09-13T21:45:29.322Z"
}

postedAt is a date, and postedText keeps LinkedIn's "6 days ago" wording beside it. The salary columns are filled on jobs with details where LinkedIn shows pay, and are null elsewhere. closingAt is always null: LinkedIn doesn't publish an expiry date on its public postings.

How many jobs can you get, and how fast?

RunResult
100 jobs with details100 jobs in 18-26 seconds
6 searches, 1,100 jobs with details1,100 jobs in 2 minutes 14 seconds (about 490 a minute)
100 jobs with Read the full job page on100 jobs in 28-32 seconds
6 searches, 1,142 jobs with Read the full job page on1,142 jobs in 3 minutes 26 seconds (about 330 a minute)

These are whole runs on Apify, measured on 5 October 2026. At that pace an hour covers roughly 25,000 jobs with details, or about 19,000 with the full job page.

LinkedIn serves at most about 1,000 results for any one search. A large run is therefore several keywords or several locations. Splitting a country into its cities is the usual way to go deeper.

How much does it cost to scrape LinkedIn jobs?

EventFree planStarterScaleBusiness
actor-start, per run$0.002$0.002$0.002$0.002
job-scanned, per listing card fetched, before dedup or filters$0.00005$0.00005$0.00005$0.00005
job-detail, per job returned with details$0.0006$0.00054$0.00048$0.00034
job-detail-enriched, per job returned with details and company data, replacing job-detail for that job$0.0006$0.00054$0.00048$0.00034
job-listed, per job returned without details$0.0002$0.00018$0.00016$0.00014

Enterprise plans pay the Business price.

$0.60 per 1,000 jobs on the Free plan and $0.34 on Business, with company details included. Nothing is added on top: proxy usage and platform usage are in that price.

Your bill follows the number of postings opened. A job removed by deduplication, by the only-new store or by a title or company filter costs the scan rate and no more. A posting that was opened is charged as a detail even if a later filter drops it. A posting that couldn't be read is returned listing-only and charged as job-listed.

  • Two keywords at 200 results each, 60 dropped by title filters, 340 jobs returned with details and company data: $0.002 + 400 × $0.00005 + 340 × $0.0006 = $0.226 ($0.138 on Business).
  • A six-hourly monitor that scans 150 cards and finds 12 new jobs: $0.002 + 150 × $0.00005 + 12 × $0.0006 = $0.017 ($0.014 on Business).

A run of 100 jobs with details costs about $0.067. On Apify's Free plan, which comes with $5 of credits a month, that's about 74 runs, or roughly 7,400 jobs, before you pay anything.

Limits: what LinkedIn doesn't show

  • About 1,000 results per search. Use "Locations (multiple)" to split a country into cities.
  • No apply URL and no expiry date. Neither is published on LinkedIn's public postings.
  • No job function. LinkedIn stopped showing it publicly (0 of 1,136 jobs in a check on 2 October 2026). Industries, seniority and employment type are returned.
  • No workplace-type column. LinkedIn doesn't expose on-site, remote or hybrid as a field.
  • Experience level, job type and workplace type no longer filter the search on LinkedIn. Here they're folded into the keywords. They steer the results strongly without being exact. Pair them with "Keep only these seniority levels" or "Keep only these employment types", which use LinkedIn's own labels on the posting.
  • Pay only where the employer states it. On 5 October 2026, 193 of 1,142 London jobs across six searches had a range (12 of 100 for "software engineer"). The rest have empty pay columns.
  • Seniority is often "Not Applicable" on the short advert: 580 of 1,100 jobs in the same check. With "Read the full job page" on, 125 of 1,142 read "Not Applicable". All other columns are identical either way.
  • A filter never guesses. "Minimum annual salary" keeps a job whose pay can't be compared with a yearly figure (an hourly rate, or no pay shown). The seniority, employment-type and description filters keep a job whose page doesn't show that field.
  • Sorting orders what the run collected. LinkedIn no longer sorts its public job search, so "Sort" can't change which jobs LinkedIn selects.

FAQ

Do I need proxies or a LinkedIn account?

Neither. The actor reads LinkedIn's public job search only, and you never sign in. Proxy usage is included in the price and there's nothing for you to configure.

How do I get only the new jobs on a schedule?

Give "Only new jobs" a store name, then schedule the run in Apify. From the second run on you get the postings that weren't there before, and the ones already seen cost $0.00005 each to skip. Set "Posted within the last N hours" a little wider than your schedule interval.

Split it. Each keyword and each location is its own search with its own ceiling, so "nurse" across twelve cities reaches far further than "nurse" in "United Kingdom".

How accurate is the posting date?

It's the date LinkedIn holds for the posting, not a guess worked back from "1 day ago". The label is kept in postedText if you want it.

Why is there no apply URL or closing date?

LinkedIn stopped publishing both on its public job pages. closingAt stays in the row as null so the columns line up with our other job scrapers, and isDirectApply tells you whether the job uses Easy Apply.

How do I make sure every row really is part-time (or entry level)?

Use the pair. Set "Job type" to part-time to steer the search, and "Keep only these employment types" to Part-time to check each posting. With both set, every returned row is part-time. The same pairing works for experience level and seniority.

What does the company data include?

Description, website, industry, size, employee count, headquarters (with street, postcode and country code in companyAddressParts), type, specialties, follower count and office addresses. Each company is fetched once and cached for 30 days by default.

The actor reads only the job postings LinkedIn serves to logged-out visitors. Those are business content, not personal profiles. Web scraping of publicly available data is generally legal, but you're responsible for complying with LinkedIn's terms and applicable law in how you use the data.

Run it on a schedule or from code

The setup we'd recommend is a monitor: an Apify Schedule every few hours with an only-new store named. A webhook can fire at the end of each run, and the new postings can go to Slack, Google Sheets, Zapier, Make or Airbyte through Apify's integrations.

From code, POST https://api.apify.com/v2/acts/boncross~linkedin-jobs-scraper/run-sync-get-dataset-items with the input JSON as the body returns the jobs in one call for short runs. Use the standard run endpoints for longer ones. Clients exist for Node.js (apify-client on NPM) and Python (apify-client on PyPI).

For an AI agent, add the Apify MCP server (mcp.apify.com) to your MCP client and the actor appears as a tool. You could ask it for today's new postings at three named companies and get a summary back.

More from BonCross

Your feedback

Spotted a LinkedIn job that came back wrong, or a field you expected and didn't get? Tell us on the Issues tab in Apify Console. We read each report and reply there, and fixes go out as new builds.