Request a tool
All toolsAutomationsGuidesMCP serverRequest a toolPlatformsCategories
LinkedIn Jobs Scraper icon

LinkedIn Jobs Scraper

Scrape public LinkedIn jobs by keyword, location, URL or ID. Filter by date, workplace type and experience. Full descriptions. $0.80 per 1,000 jobs.

146 runs on Apify $0.0008 per LinkedIn job ($0.8 / 1,000)
Run this in the cloudRun on Apify →

Job Market Scrapers

How it works

  1. 1
    Open it on Apify

    Hit Run on Apify — it opens the tool in the cloud, no install.

  2. 2
    Set the inputs

    Adjust searchQueries, locations, country (sensible defaults are pre-filled).

  3. 3
    Click Run

    The tool runs on Apify’s cloud and collects the data for you.

  4. 4
    Export the results

    Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.

Pricing

$0.0008 per LinkedIn job = $0.8 per 1,000

You are charged forWhenPrice
LinkedIn jobOne successfully saved LinkedIn job listing.$0.0008

Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-04, and they are what you are actually charged.

Inputs

FieldWhat it doesType
searchQueriesJob titles or keywords. Every query is searched against every location. Leave empty when using direct job URLs or IDs.array
locationsCities, regions, or countries. Every location is combined with every query. Leave empty for an unrestricted location search.array
countryOptional country name appended to each search location, for example Canada or United States. It is also used alone when no location is supplied.string
jobUrlsPublic LinkedIn /jobs/view/ URLs to fetch directly. URLs and IDs are deduplicated with search results.array
jobIdsNumeric LinkedIn job IDs to fetch directly.array
datePostedLinkedIn's server-side posting-age filter.string
easyApplyOnly jobs you can apply to on LinkedIn itself, without being sent to the company's own site.boolean
under10ApplicantsOnly jobs few people have applied to yet. This is LinkedIn's own filter.boolean
companyIdsOnly jobs from these companies, one LinkedIn company id per line, such as 1441 for Google. To find an id, filter jobs by the company on LinkedIn and copy the number after f_C= in the address bar; pasting that whole address works too. A company name won't work.array
distanceHow far from each location to look, in miles. Needs at least one location.string
includeDetailsFetch each job detail page for description, seniority, employment type, job function, industries, and applicant count. Direct URLs and IDs always fetch details. Turning this off makes searches faster and cheaper.boolean
maxItemsMaximum unique real job rows across all searches, URLs, and IDs.integer
maxPagesPerSearchSafety limit for each query/location combination. LinkedIn currently returns about 10 jobs per guest page.integer
countryCodeOptional two-letter country code, for example US, CA, GB or DE. Used only if a direct request is refused and the fallback is needed.string
maxProxyRetriesHow many times to retry one refused request before giving up on it.integer
requestTimeoutSecsTimeout for each lightweight LinkedIn guest endpoint request.integer

What you get

A structured dataset — each result includes fields like:

titlecompanylocationworkplaceTypeemploymentTypepostedAturl

Export every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.

Ready-made automation using this tool

A finished workflow you can import into n8n and run — this tool does the data-gathering inside it. Free, and yours to change.

Spot companies about to buy, from what they are hiring for

A company hiring its first support manager is telling you it is about to need support tooling. This reads job posts, works out what each hire implies the company will need, scores how well that matches what you sell, and files only the strong ones in Notion.

All automations →

Related tools in Job Market Scrapers

Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.

BuiltIn Jobs Scraper iconJob Market Scrapers

BuiltIn Jobs Scraper

Scrape Built In tech jobs: salary, all locations, skills, seniority, exact posted date. No login, no API key. $0.81 per 1,000.

Ready to run — no setup

Dice Jobs Scraper iconJob Market Scrapers

Dice Jobs Scraper

Scrape Dice jobs: title, company, location, type, posting age and apply URL. Descriptions optional. No login. $0.90 per 1,000 jobs.

Ready to run — no setup

SEEK Jobs Scraper iconJob Market Scrapers

SEEK Jobs Scraper

Scrape SEEK jobs in Australia and New Zealand: salary ranges, workplace type and full descriptions. No login. $0.81 per 1,000, flat at every volume.

Ready to run — no setup

Career Site Jobs Scraper iconJob Market Scrapers

Career Site Jobs Scraper

Scrape open jobs from a career page, a domain or a company name. Works with 10 ATS platforms. Get title, location, department and apply URL.

Ready to run — no setup

Internshala Scraper iconJob Market Scrapers

Internshala Scraper

Scrape Internshala internships and fresher jobs by keyword, city, category, stipend or work from home. Duration, apply-by date, openings. $0.34/1,000.

Ready to run — no setup

XING Jobs Scraper iconJob Market Scrapers

XING Jobs Scraper

Scrape XING jobs in Germany, Austria and Switzerland. Company, employment type, career level, posted date, apply URL and salary. $0.51 per 1,000 jobs.

1 use cases

See all Job Market Scrapers →

LinkedIn Jobs Scraper: public job postings by keyword, location, URL or ID

Search LinkedIn jobs without an account and get one row per posting: 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 itself 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, or direct job URLs and IDs
OutputOne row per job
Ceiling5,000 jobs per run
Account neededNone
Price$0.80 per 1,000 jobs, flat on every plan

💼 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. Remote, job type, experience level and newest first are missing on purpose. LinkedIn ignores them on a public search, so offering them would only look like filtering.

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.

📥 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.
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 guest results page holds about ten jobs, so ten pages is roughly a hundred per query and location.
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 to ask of one run. Split that into batches of a few hundred and you will have a better time of it.

📤 What you get back

A real row from a recent run, 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
}

That is what a row looks like with includeDetails off. Everything below postedText fills in when it is on.

FieldWhat it is
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.
description, descriptionHtmlThe posting text, plain and with markup. Detail pages only.
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

Three kinds of row, and only real jobs cost anything.

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.

One ordering quirk worth knowing: diagnostics are written as they happen, while job rows are written at the end of the run. So in dataset order the problems come first, and a run you abort half way through leaves you with the diagnostics and no jobs.

A diagnostic row carries an errorCode:

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, jobTypes, experienceLevels or sortBy: "recent", which LinkedIn ignores. Nothing is searched.
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.
BLOCKEDLinkedIn answered with a wall instead of results. Give it a few minutes.
NETWORKThe request failed or did not arrive in time.

▶️ How to run it

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?

$0.80 per 1,000 jobs. Flat on every Apify plan, no volume tiers.

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.

💡 What people use it for

  • Watching a set of titles in a set of cities on a schedule, and diffing the new ids against

yesterday's.

  • 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, no recruiter names, no contact details. None of that is on a public job

page.

  • 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, no job type or experience level filter, and no newest

first.** LinkedIn ignores all four on a public search and sends back the same jobs, so a search that sets one stops with a message and nothing is charged.

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

  • No industry filter. LinkedIn's public job search accepts one and quietly ignores it, so it

would only look like filtering. With includeDetails on, every row lists the job's industries, so you can filter on those yourself.

  • A search stops at the pages you allowed. A wide query will always have more behind it than

one run returns.

  • No jobs that were never public, and none that have already been taken down.

🧭 Which job scraper do you need?

If you wantUse
LinkedIn postingsThis one
Indeed postingsIndeed Jobs Scraper
Google's aggregated job resultsGoogle Jobs Scraper
Jobs straight from company career sitesCareer Site Jobs Scraper
The company page behind a postingLinkedIn Companies 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 filter by salary? No. Too few postings publish one for that to be a useful filter.

How fresh is postedAt? It is the posting's own timestamp, so it is as accurate as what the employer set. Use datePosted if you only want recent ones.

Is scraping LinkedIn jobs legal? These are public pages LinkedIn publishes for search engines. Apify's write-up on scraping and the law 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.