LinkedIn Jobs Scraper - Jobs by Keyword and Location avatar

LinkedIn Jobs Scraper - Jobs by Keyword and Location

Pricing

from $0.77 / 1,000 linkedin jobs

Go to Apify Store
LinkedIn Jobs Scraper - Jobs by Keyword and Location

LinkedIn Jobs Scraper - Jobs by Keyword and Location

Scrape public LinkedIn jobs by keyword, location, search link, job URL or ID. Each row has the title, company, location, posting date and job URL, plus the description, seniority and company details when you want them. Filter by date, company, title words or distance. $0.80 per 1,000 jobs.

Pricing

from $0.77 / 1,000 linkedin jobs

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Scrape public LinkedIn jobs by keyword, location, search link, job URL or job ID, with no login: one row per posting with the title, company, location, posting date, the canonical job URL and, when you ask for it, the full description, the seniority, the employment type and the applicant count.

The search works signed out because a job posting is a public page. What you get by default is the card, the same block of text you see in a results list. The description lives on the job's own page and is only fetched when you switch includeDetails on.

InputKeywords and locations, LinkedIn search links, or direct job URLs and IDs
OutputOne row per job: title, company, location, posted date, URL; with details, description, seniority, type, applicants
Ceiling5,000 jobs per run
Account neededNone
Price$0.80 per 1,000 jobs on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 6,200

🔍 What LinkedIn Jobs Scraper does

Give it job titles and places. Every query is run against every location, so three titles and four cities is twelve searches, and the results are pooled and deduplicated into one dataset. A job that two searches both find is written once and charged once.

Every filter here is LinkedIn's own, applied by LinkedIn before the results come back: date posted, companies, Easy Apply, under 10 applicants and distance. They narrow the search rather than just shrinking the output. LinkedIn ignores job type, experience level and industry, so those are checked on each job's own page, and you pay only for jobs that match. Remote and newest first can't be checked, so they're missing.

You can also skip searching. Paste /jobs/view/ URLs or numeric job IDs and they are fetched directly, with their full detail pages, and merged with anything the searches found. Or set up a search on LinkedIn signed out and paste its address: it runs with its own filters.

Some things are done here rather than by LinkedIn: title words keep or drop jobs before anything is charged, ids you already have are skipped, a company name becomes its id, and a whole country can be searched city by city to get past the 1,000 or so jobs LinkedIn lists per search.

📋 What data you get from each LinkedIn job

What you getField
LinkedIn's job id and the canonical job URLjobId, url
Title, company, its LinkedIn page and logotitle, company, companyUrl, companyLogo
Location and salary, as the card shows themlocation, salary
The posting date, and LinkedIn's own wording for itpostedAt, postedText
With details on: employment type, seniority, job function, industries, applicantsemploymentType, seniorityLevel, jobFunction, industries, applicants
With details on: the posting text, plain and with markupdescription, descriptionHtml
Where the row came from, and whether the job page was openedsourceType, searchQuery, searchLocation, detailFetched
With company details on: the company's id, industry, size, headquarters, type and websitecompanyId, companyIndustry, companySize, companyEmployeesOnLinkedIn, companyHeadquarters, companyType, companyWebsite, companyDetailsFetched
With the job poster on: who posted it, when the page shows themhiringContact (name, headline, profileUrl, photoUrl)
Always empty, kept for older integrationsworkplaceType

▶️ How to scrape LinkedIn jobs

  1. Open LinkedIn Jobs Scraper and click Try for free.
  2. Put job titles in Search queries and places in Locations.
  3. Set Date posted and any other filter you want LinkedIn to apply.
  4. Turn on Fetch full job details if you need the description, then set Maximum jobs.
  5. Click Start, then download the dataset as JSON, CSV or Excel, or read it from the API.

💰 How much does it cost to scrape LinkedIn jobs?

$0.80 per 1,000 jobs on the Free plan, $0.79 on Starter, $0.78 on Scale and $0.77 on Business. The free plan's $5 a month covers about 6,200 jobs.

One charge per unique job row. A posting that several of your searches all find is written once and billed once. Sample rows and diagnostic rows are never charged, and a search that finds nothing costs you nothing for results. Fetching the full descriptions does not change the price, and jobs your job type, experience or industry filters leave out are read but not charged. If you set a maximum cost for the run, it stops when that is reached.

📥 What you give it

{
"searchQueries": ["software engineer"],
"locations": ["Toronto, Ontario"],
"datePosted": "pastWeek",
"includeDetails": true,
"maxItems": 200
}
FieldDefaultWhat it is
searchQueriesprefilled with an exampleJob titles or keywords. Each one is searched against each location.
locationsprefilled with an exampleFree text, passed to LinkedIn as typed. "Toronto, Ontario", "Germany", "Greater Boston".
countryemptyA country name appended to each location, and used on its own when you give no location.
jobUrlsemptyPublic /jobs/view/ URLs to fetch directly.
jobIdsemptyNumeric job IDs, same thing without the URL around them.
datePostedanyany, past24h, pastWeek, pastMonth.
easyApplyoffOnly jobs you apply to on LinkedIn itself, not on the company's own site.
under10ApplicantsoffOnly jobs few people have applied to yet. LinkedIn's own filter.
companyIds[]Only these companies' jobs, as LinkedIn company ids such as 1441 for Google. A name is refused: LinkedIn would ignore it and return every company.
distanceany5, 10, 25, 50 or 100 miles around each location. Needs a location.
jobTypes[]fullTime, partTime, contract, temporary, internship, volunteer, other. Checked on each job's page.
experienceLevels[]internship, entry, associate, midSenior, director, executive. Checked on each job's page.
industries[]LinkedIn industry names, such as Software Development. A job matches if any of its industries is listed.
includeDetailsoffOpens each job's own page for the description, seniority, employment type, job function, industries and applicant count. Direct URLs and IDs always do this.
maxItems1001 to 5,000. Unique jobs across the whole run.
maxPagesPerSearch101 to 100. A results page holds about ten jobs, so ten pages is roughly a hundred per query and location.
searchUrls[]LinkedIn job search links, each run with its own filters. Workplace type and newest first in a link are refused.
companyNames[]Company names, turned into ids before the search. A name that matches no company exactly stops the run.
titleIncludes, titleExcludes[]Phrases. Keep a job whose title holds every word of one; drop one whose title holds every word of any.
skipJobIds[]Job ids or links you already have. Left out, not charged, and the search carries on past them.
splitByCityoffSearches a whole-country location city by city, 8 to 50 cities depending on the country.
includeCompanyDetailsoffAdds the company's details from its LinkedIn page. One page per company.
includeHiringContactoffAdds the job poster when the job page shows one. Reads each job's page.
requestTimeoutSecs205 to 60 seconds per request.
proxyConfiguration, countryCode, maxProxyRetriesas they comeAdvanced network settings. The defaults suit almost every run. Leave them alone unless you have a reason.

Switch includeDetails on if you want the job text. It is off out of the box, and without it description, seniorityLevel, employmentType and applicants are null on every search row. It costs the same per job either way.

Full descriptions on thousands of jobs is a lot for one run. Split it into batches of a few hundred.

📤 What you get back

A real row from a card-only search, with the logo link cut short:

{
"ok": true,
"sourceType": "search",
"jobId": "4445788134",
"title": "Software Engineer (C++) - Platform & Emerging Technologies",
"company": "Autodesk",
"companyUrl": "https://www.linkedin.com/company/autodesk?trk=public_jobs_jserp-result_job-search-card-subtitle",
"companyLogo": "https://media.licdn.com/dms/image/v2/D560BAQGrSi2UOCdL5g/company-logo_100_100/...",
"location": "Toronto, Ontario, Canada",
"salary": null,
"postedAt": "2026-09-10",
"postedText": "3 days ago",
"workplaceType": null,
"employmentType": null,
"seniorityLevel": null,
"jobFunction": [],
"industries": [],
"applicants": null,
"description": null,
"descriptionHtml": null,
"url": "https://www.linkedin.com/jobs/view/4445788134",
"searchQuery": "software engineer",
"searchLocation": "Toronto, Ontario, Canada",
"detailFetched": false
}
FieldHow to read it
jobIdLinkedIn's own id. Your dedupe key, and the thing to store if you re-check postings later.
postedAtThe date from the posting's own timestamp. postedText keeps LinkedIn's wording, "3 days ago", for when you want what the page said.
salaryOnly what the card states, which for most postings is nothing.
workplaceTypeAlways empty. LinkedIn's public job pages don't say whether a job is remote, hybrid or on-site.
applicantsLinkedIn's applicant count, detail pages only, and it is a rounded figure on their side.
industriesWith details on, the job's industries, each matched whole against LinkedIn's published list.
detailFetchedWhether that job's own page was opened. The fastest way to tell why a field is empty.
sourceTypesearch for a job a search found, direct for one you supplied by URL or id.

🧾 Reading the output

RowHow to spot itCharged
A jobsourceType: "search" or "direct"yes
The sample row_sample: true, on a run with no usable inputno
A diagnosticok: false and _diagnostic: trueno

There is no charged field on these rows. sourceType is what separates a real job from a sample or a diagnostic.

Jobs and diagnostics are written as they happen, so a run you stop half way keeps the jobs it found, and only those are charged.

CodeWhat it means
BAD_INPUTA job URL that is not a /jobs/view/ link, an id that is not numeric, a company given as a name instead of an id, a distance with no location, or a search that sets workplaceType or sortBy: "recent", which LinkedIn ignores and no page shows, or a job type, experience level or industry name it does not know, a search link with a filter it cannot apply, a company name that matches no company, or Split by city with no whole country to split. Nothing is searched.
FILTER_TOO_RAREAfter 50 job pages under 5% matched your job type, experience or industry, so the run stopped reading. What matched is delivered.
PAGE_CAPThe run read three job pages for every job you asked for. What matched is delivered.
NO_RESULTSThat query and location combination returned nothing. It also appears when everything a search found had already been returned by an earlier search in the same run.
NOT_FOUNDA direct job URL or id that LinkedIn no longer has. Usually a filled or withdrawn posting.
PARSE_ERRORThe detail page came back without the fields that make a job row.
NOT_SERVEDThis job was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED.
NETWORKThe request failed or did not arrive in time.
TIME_LIMITThe run got close to its time limit and stopped on its own. The jobs found before that are delivered and charged; give it more time or ask for fewer jobs to get the rest. It ends as failed only when no job was found.

💡 What people use it for

  • Watching a set of titles in a set of cities on a schedule, with yesterday's ids in skipJobIds so only new postings are charged.
  • Spotting which companies are hiring into a function right now, as a buying signal.
  • Pulling descriptions for a market to see how a role is actually scoped and worded.
  • Checking whether a specific posting is still live, by feeding its id back in.

🚧 What it does not do

  • No applicant lists and no contact details. The job poster's name and headline come only with includeHiringContact, and only when the public page shows one, which is a minority of jobs.
  • No salary for most postings. The field is there and it carries whatever the card says, which is usually nothing. LinkedIn does not publish a salary unless the poster did.
  • No applying for you, and no saved jobs. It can find Easy Apply jobs, but it only reads.
  • No remote, hybrid or on-site filter, and no newest first. LinkedIn ignores both on a public search and a job page doesn't say them, so a search that sets one stops with a message and nothing is charged.
  • Rare filters make slow runs. Each job's page is read to check them, and most postings print "Not Applicable" as seniority, so a narrow filter reads many pages for few jobs. Under 5% matching after 50 pages, the run stops and says so.
  • Location is text. It goes to LinkedIn as typed. Set distance to say how far around it to look; otherwise LinkedIn decides what counts as nearby.
  • A search stops at the pages you allowed. A wide query will always have more behind it than one run returns; splitByCity reaches further for a whole country.
  • No jobs that were never public, and none that have already been taken down.
  • It is not an official LinkedIn tool. Dami's Studio is independent and is not affiliated with or endorsed by LinkedIn, or by any other company named on this page.

🧭 Which job scraper do you need?

If you wantUse
Public LinkedIn jobs by keyword, location, URL or IDThis one
The company page behind a posting: followers, employee count, headquartersLinkedIn Companies Scraper
Open jobs at companies you name, read from their own hiring systemCareer Site Jobs Scraper
Remote jobs, with the region the employer hires fromRemotive Jobs Scraper

❓ Questions people ask

Do I need a LinkedIn account?

No, and there is no cookie field. Job pages are public.

Why is the description empty?

Because includeDetails was off. Check detailFetched on the row: false means that job's own page was never opened.

Why did I get fewer jobs than I asked for?

Either the search genuinely has fewer, or maxPagesPerSearch stopped it. Widen the query, raise the page limit, or add locations.

Can I call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/linkedin-jobs-scraper. Either way the run happens on your Apify account at the same price.

These are public job pages anyone can open without an account. If a posting names a person, that is personal data under GDPR and similar laws, so have a reason for keeping it. Apify's write-up on the legality of web scraping is a reasonable starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the run ID and the exact query and location. The errorCode and searchQuery on the diagnostic row usually point straight at it.