LinkedIn Jobs Scraper - Job Postings & Salaries, No Login avatar

LinkedIn Jobs Scraper - Job Postings & Salaries, No Login

Pricing

from $0.002 / actor run started

Go to Apify Store
LinkedIn Jobs Scraper - Job Postings & Salaries, No Login

LinkedIn Jobs Scraper - Job Postings & Salaries, No Login

Search public LinkedIn job postings by keyword, location and filters. Get title, company, location, posted date and URL, or the full description, seniority, employment type, applicants and salary. No login or cookies. For recruiters, job boards and labour-market research.

Pricing

from $0.002 / actor run started

Rating

0.0

(0)

Developer

SR

SR

Maintained by Community

Actor stats

0

Bookmarked

8

Total users

4

Monthly active users

14 days ago

Last modified

Share

LinkedIn Jobs Scraper: Job Postings, Descriptions and Salaries Without Login

This LinkedIn jobs scraper searches public LinkedIn job postings by keyword and location and returns the search cards or the full vacancy descriptions, for recruiters, job boards and labour-market research. It requires no LinkedIn login, cookies or account connection. Search for a title, a skill or an employer, add a city or country, and receive structured records that can be exported from the Apify dataset as JSON, CSV or Excel.

With full details enabled, each result includes the description in HTML and plain text, the employer, employment type, seniority, published dates, applicant count and advertised salary when the posting contains those fields. Listings-only mode returns the information visible on the search card and uses the lower listing price. Every posting keeps LinkedIn's job id for matching repeated observations in your own database.

LinkedIn Jobs Scraper input

The only required field is keywords. The default example searches for data engineer in Netherlands. Use location for a city, region or country as LinkedIn spells it; leave it empty for a worldwide search. limit defaults to 25 and accepts 1 through 500. detail defaults to true. Set it to false when you only need title, employer, place, posted date and URL.

The supported filters follow LinkedIn's public search vocabulary:

  • posted_within: any, 24h, week or month.
  • workplace: any, on_site, remote or hybrid.
  • job_type: any, full_time, part_time, contract, temporary, internship or volunteer.
  • experience: any, internship, entry_level, associate, mid_senior, director or executive.
  • sort_by: relevance or date.

All filters default to any; sorting defaults to relevance. retries defaults to 3, accepts 1 through 6, and controls how many attempts may be made for each source request within its time budget. The maximum result count is a ceiling: a narrow query or a source interruption can return fewer postings.

This input was used for a real run:

{"keywords":"data engineer","location":"Netherlands","limit":25,"retries":3}

LinkedIn jobs scraper output

One dataset row represents one vacancy. All rows contain job_id, url, title, company, company_url, location, posted_at, posted_label, company_logo, detail_fetched, position, keywords and search_location. Positions start at one and continue across the collected results. Tracking query parameters are removed from the job and company links.

This complete listing row was retrieved on 2 October 2026:

{
"job_id": "4463254080",
"url": "https://uk.linkedin.com/jobs/view/senior-product-manager-exchange-at-cint-4463254080",
"title": "Senior Product Manager, Exchange",
"company": "Cint",
"company_url": "https://se.linkedin.com/company/cint",
"location": "London, England, United Kingdom",
"posted_at": "2026-09-29",
"posted_label": "3 days ago",
"company_logo": "https://media.licdn.com/dms/image/v2/D560BAQFcxpX_AYLRIw/company-logo_100_100/company-logo_100_100/0/1730109376559?e=2147483647&v=beta&t=6DgV2Eiy6ZMdA3-ygKZf1rGb1c7enVCuE4E4a8nhhmU",
"detail_fetched": false,
"position": 1,
"keywords": "product manager",
"search_location": "London",
"source": "linkedin-jobs-scraper",
"platform": "linkedin",
"fetched_at": "2026-10-02T14:33:41.217Z"
}

With detail enabled, the same row gains the posting's own fields. This excerpt of a real detailed row (search python developer in Germany, remote, full time, retrieved 2 October 2026) shows a selection of them:

{
"job_id": "4467502615",
"title": "(Senior) Software Developer Backend / Python",
"company_name": "Athereon GRC GmbH",
"city": "Saarbrücken",
"country": "DE",
"employment_type": "FULL_TIME",
"seniority_level": "Berufserfahren",
"applicants_count": 60,
"salary_min": null,
"salary_max": null,
"salary_currency": null,
"salary_unit": null,
"date_posted": "2026-10-02T10:07:18.000Z",
"detail_fetched": true,
"detail_source": "json_ld"
}

A successful detailed row adds the following original fields. Missing published values remain null; these fields are absent from listing-only rows. The original field names and JSON types remain available.

FieldsJSON typeContent
detail_sourcestringjson_ld for structured posting data or dom for visible content.
description_html, description_textstring or nullFormatted and plain-text vacancy descriptions.
company_name, company_linkedin_urlstring or nullEmployer name and LinkedIn URL from the posting.
country, city, region, postal_code, street_addressstring or nullPublished country code and address components.
employment_type, employment_type_label, seniority_levelstring or nullStructured employment type and the posting's visible employment and seniority labels.
industry, skills, job_function, industriesstring or nullStructured industry and skills, plus visible job criteria. job_function retains its historical positional value; industries also contains the industry when that criterion is published.
criteriaobject or nullVisible criterion labels mapped to their values, in the posting's language.
date_posted, valid_throughstring or nullPublished posting and expiry dates.
applicants_labelstring or nullThe visible applicant label, in the posting's language.
applicants_countinteger or nullThe number read from the visible label, including labels that describe a lower bound.
apply_urlstring or nullAn application link when the posting publishes it.
salary_min, salary_maxnumber or nullPublished lower and upper salary bounds.
salary_currency, salary_unitstring or nullPublished salary currency and period.

Additional common fields are source, platform and fetched_at. Detailed rows keep the original country, salary_unit and description_text fields, including null values when a posting omits that information. detail_source tells you whether a detailed posting was read from its structured data or its visible content.

The summary key-value record reports the delivered item count, errors, fetched search pages, found listings, completed details, whether details were requested and the elapsed fetching time. If individual requests fail, the errors record explains them. A failed detail request leaves the search card in the dataset, with detail_fetched: false.

Pricing

Pricing remains pay per event. run_start costs $0.002 once per run, including runs with no results. Each delivered card without full details costs $0.0006 through job_listing. Each delivered vacancy with successfully fetched details costs $0.004 through job_detail. A vacancy receives one of those two result charges. A failed detail attempt is billed as the delivered listing card, rather than as a full detail.

For example, 25 delivered full details cost $0.102 including the start event. Thirty listing cards cost $0.020 including the start event. An empty search costs only the $0.002 start event. These amounts describe the actor's event prices; consult the live pricing panel for the platform's current billing presentation.

Free-plan users receive at most ten results per run. Only delivered results are charged. Paid-plan users can request the full supported volume. There is no separate subscription to configure for this actor.

Use cases

Recruiters can collect open roles in a city and compare employers, seniority and applicant counts. Job aggregators can collect descriptions and keep their own index, matching repeated observations by job_id. Salary researchers can use published salary bounds, currency and period when available. Text-processing workflows can use the full plain description while retaining the formatted HTML for display.

For repeated collection, combine sort_by: date with posted_within: 24h and compare job ids against your stored observations. Repeating a search can return the same vacancy again; deduplication across separate runs belongs in your own storage. Within one run, each job id is delivered at most once.

How this LinkedIn jobs scraper compares

The Apify Store has several LinkedIn job actors. Most charge one flat price for every dataset item, whatever the item contains; at the time of writing those prices range from about $0.0004 to $0.002 per item on the free plan, often lower on higher plans. This actor splits the price by depth instead:

  • Listing cards cost $0.0006 each. For a market scan of title, employer, place and date, that is in the low range of what the Store charges.
  • Full details cost $0.004 each and include the HTML and plain-text description, criteria, applicants, skills and published salary fields. That is more than a flat-rate item, so use it when you need the description itself.
  • A detail attempt that fails is billed as a listing card, not as a detail.
  • The input needs no LinkedIn account, cookies or session, so there is nothing to renew and no personal account at risk.

If you need data the public pages do not show, such as recruiter contact details or private company data, this actor is not the right tool: it returns what a logged-out visitor can see.

Limits and data availability

Search results change as employers publish, update or remove vacancies. A job can disappear between the search and the detail request. Applicant counts and relative posted labels are observations at retrieval time. Criteria labels and values follow the posting's market language; the structured employment type and country code are separate fields.

Salary appears only when the employer provides structured salary data. A number mentioned in prose is not automatically treated as an advertised salary range. Some pages lack structured data, so their visible description and company are returned through the DOM fallback while fields unavailable there remain null.

Large requests are collected in resumable pages internally. Apify follows that continuation automatically. If the run's available time is exhausted, collected rows remain available and the summary reports a warning about remaining work. A query with no matching jobs returns a successful empty dataset. Temporary source blocks also produce a successful empty outcome when no usable results can be retrieved.

FAQ

Can I scrape LinkedIn jobs without login or cookies?

Yes. The actor reads publicly accessible vacancies and does not ask for a LinkedIn account or session. It returns only information available on those public pages.

How do I get only listing cards?

Set detail to false. The actor returns search-card fields and charges the listing event for each delivered vacancy. This is useful for an initial market scan before collecting full descriptions for a narrower query.

Can I call the LinkedIn Jobs Scraper from my own code?

Yes. Use Apify's actor run API with the same JSON input, then read the default dataset. Existing integrations retain their input names, defaults and original output fields.

Why are salary or employment fields null?

The employer may not publish those values, or the page may expose only visible content rather than structured data. Check detail_fetched and detail_source; null fields do not imply an invented estimate.

Is this an official LinkedIn jobs API?

No. LinkedIn's own job APIs are limited to approved partners. This actor works as a LinkedIn jobs API for everyone else: you send keywords, a location and filters as JSON through the Apify API and receive structured job postings back, without a partner agreement.

How many jobs can I get per run?

Up to 500 postings per run on a paid plan, ten on the free plan. LinkedIn's public search shows a limited number of results for one query, so for wide markets split the search by city, job type or posting date and combine the runs by job_id.

Does a repeated run remove yesterday's vacancies?

No. Each run returns the source observations for that run. Use job_id and fetched_at to maintain your own history and decide how to handle postings that are no longer returned.