LinkedIn Advanced Jobs + Recruiter Details Scraper avatar

LinkedIn Advanced Jobs + Recruiter Details Scraper

Pricing

from $1.80 / 1,000 job-results

Go to Apify Store
LinkedIn Advanced Jobs + Recruiter Details Scraper

LinkedIn Advanced Jobs + Recruiter Details Scraper

Scrape public LinkedIn job listings by keyword, location, or URL into clean, CSV-ready rows with hiring-signal fields and visible recruiter indicators - no login, cookies, or Apify residential proxy.

Pricing

from $1.80 / 1,000 job-results

Rating

0.0

(0)

Developer

Delowar Munna

Delowar Munna

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

LinkedIn Advanced Jobs + Recruiter Details Scraper

Scrape public LinkedIn job listings by keyword + location or by direct LinkedIn job URL, and turn them into clean, flat, CSV-ready rows — with lightweight hiring-signal fields, tech-keyword tags, salary visibility, remote signals, and public recruiter indicators (recruiter name / profile link only when visibly present on the public job page). Built for recruiters, staffing agencies, sales teams, lead-generation teams, and market researchers.

No LinkedIn login, no cookies, no session IDs. The actor uses LinkedIn's public guest jobs surface over HTTP, so it stays fast and cost-predictable. You pay one flat event per unique job row that passes your filters.

✨ Why this scraper

  • Public-only & transparent — no login, cookies, sessions, credentials, or Apify residential proxy. It scrapes only what is publicly visible.
  • Visible recruiter signals — captures recruiter name / profile URL when LinkedIn shows them publicly on the job page (no profile visits, no enrichment). Recruiter info is sparse on public pages; fields default to not_visible when absent.
  • Two input modes — keyword + location, or paste LinkedIn job search URLs and direct job-detail URLs (/jobs/view/{id}).
  • Flat, CSV-ready rows — job identity, company, role metadata, posting details, recruiter signals, and derived hiring signals. No nested objects.
  • Pay-Per-Event — one flat job-result event per saved unique job. Duplicates and filtered rows are never charged.
  • Transparent hiring-signal score — rule-based (no AI), explained below.

🚀 Quick start — sample inputs

Example 1 — keyword + location

{
"keywords": ["software engineer", "data analyst"],
"locations": ["Sydney, New South Wales, Australia", "Melbourne, Victoria, Australia"],
"maxResults": 100,
"datePosted": "past_week",
"remoteMode": "any",
"includeRecruiterVisibleOnly": false,
"requireSalaryVisible": false,
"includeDescription": true,
"includeHiringSignals": true,
"deduplicate": true,
"proxyConfiguration": { "useApifyProxy": true }
}

Example 2 — direct job URLs + remote filter + custom residential proxy via your own provider

{
"startUrls": [
"https://www.linkedin.com/jobs/view/3912345678/",
"https://www.linkedin.com/jobs/search/?keywords=sales%20manager&location=United%20States&f_TPR=r604800"
],
"maxResults": 250,
"remoteMode": "remote",
"requireSalaryVisible": true,
"includeDescription": true,
"includeHiringSignals": true,
"deduplicate": true,
"proxyConfiguration": {
"useApifyProxy": false,
"proxyUrls": ["http://user:pass@proxy.iproyal.com:12321"]
}
}

Provide at least one of keywords (with optional locations) or startUrls. startUrls accepts both jobs search URLs and direct job-detail URLs. If you provide both inputs, the actor runs both and deduplicates across the whole run.

The actor blocks Apify Residential proxy; if you need residential routing, supply your own provider via proxyConfiguration.proxyUrls. See 🚦 Proxy policy below.


📦 Output

The dataset has one view: Jobs, recruiter signals & hiring signals — a flat table (29 columns).

LinkedIn Advanced Jobs + Recruiter Details Scraper — all fields table view

Output fields (29)

job_id, job_url, source_url, input_type, title, company_name, company_linkedin_url, location, workplace_type, employment_type, seniority_level, job_function, industries, posted_date_text, applicants_text, description_text, apply_url, recruiter_name, recruiter_profile_url, recruiter_visibility, salary_text, salary_visible, remote_signal, tech_keywords, hiring_signal_score, hiring_signal_label, reason_tags, is_filtered_out, scraped_at.

input_type is generated_search (from keywords), search_url (pasted search URL), or job_url (pasted job-detail URL). recruiter_visibility is visible, not_visible, or blocked.

Sample record

Real run output; description_text is truncated here for readability.

{
"job_id": "4413496469",
"job_url": "https://www.linkedin.com/jobs/view/4413496469",
"source_url": "https://www.linkedin.com/jobs/search/?keywords=software+engineer&location=Sydney%2C+New+South+Wales%2C+Australia",
"input_type": "generated_search",
"title": "Software Engineer, Intern",
"company_name": "Stripe",
"company_linkedin_url": "https://www.linkedin.com/company/stripe",
"location": "Sydney, New South Wales, Australia",
"workplace_type": "onsite",
"employment_type": "internship",
"seniority_level": "entry",
"job_function": "Engineering and Information Technology",
"industries": "Software Development, Financial Services, and Technology, Information and Internet",
"posted_date_text": "4 days ago",
"applicants_text": "Over 200 applicants",
"description_text": "Who we are. About Stripe. Stripe is a financial infrastructure platform for businesses... The annual salary range for this role in the primary location is A$100,800 - A$100,800...",
"apply_url": null,
"recruiter_name": null,
"recruiter_profile_url": null,
"recruiter_visibility": "not_visible",
"salary_text": "$100,800",
"salary_visible": true,
"remote_signal": "onsite",
"tech_keywords": "java; javascript; go; ruby; scala",
"hiring_signal_score": 80,
"hiring_signal_label": "high",
"reason_tags": "complete_job_detail; recent_posting; salary_visible; remote_signal; tech_role",
"is_filtered_out": false,
"scraped_at": "2026-06-07T08:49:54.343Z"
}

Recruiter fields (recruiter_name, recruiter_profile_url) populate only when LinkedIn publishes them on the public job page, which is uncommon — most rows return recruiter_visibility: "not_visible". The actor never logs in or visits profiles. See 🚧 Limitations.


🎯 Hiring-signal score

Transparent rule-based score (0–100) computed from extracted fields — no AI, no external enrichment. Included when includeHiringSignals: true (otherwise the three signal fields are null).

SignalPoints
Job title exists+20
Company name exists+15
Description exists and > 300 chars+10
Location exists+10
Posted date text suggests recent activity+10
Apply URL exists+10
Recruiter info visible+10
Salary visible+10
Employment type or seniority visible+5

Score is capped at 100.

Labels: high (70–100) · medium (40–69) · low (0–39).

reason_tags is a ; -separated list explaining the row — e.g. recent_posting, recruiter_visible, salary_visible, remote_signal, tech_role, external_apply_url, complete_job_detail.


💰 Pricing

Pay-Per-Event. One flat event per saved row (final per-event price is configured on the Apify console):

EventCharged when
job-resultOnce per unique job row that passed all filters and was successfully written to the dataset.

So your bill is simply results_saved × price_per_event. The actor honors the user-configured per-run spending cap (Apify eventChargeLimitReached): it both caps how many results it collects up-front to what the limit can pay for, and stops cleanly the moment the cap is reached during charging.

Not charged:

  • Duplicates (deduplicated by job_id, canonical job_url, and title-based keys).
  • Rows filtered out by remote-mode / recruiter-visible / salary-visible / date filters.
  • Rows missing a job_id/job_url or title + company_name.
  • Failed or blocked requests.

🚦 Proxy policy

Use Apify Datacenter proxy or no proxy for normal runs — both work for LinkedIn's public guest jobs surface at this actor's conservative concurrency.

Apify Residential proxy is not supported. The actor will fail at startup if proxyConfiguration.apifyProxyGroups includes RESIDENTIAL. Reason: in pay-per-event actors, residential bandwidth (~/GB) is billed to the developer, not the run user, so a single bandwidth-heavy run could exceed the per-result event revenue.

If you genuinely need residential routing, supply your own residential provider via the proxy editor's Custom proxy URLs field — that traffic goes through your provider, not Apify, and is unaffected:

http://user:pass@proxy.iproyal.com:12321
http://user:pass@proxy.brightdata.com:22225
http://user:pass@proxy.oxylabs.io:7777

📊 Run summary

After each run, a RUN_SUMMARY entry is written to the key-value store:

{
"inputs_total": 4,
"successful_inputs": 3,
"failed_inputs": 1,
"generated_search_urls": 4,
"job_urls_discovered": 0,
"raw_results_found": 420,
"results_saved": 100,
"duplicates_removed": 37,
"filtered_out": 19,
"charged_events": 100,
"blocked_requests": 2,
"login_wall_detected": 0,
"retry_count": 8,
"runtime_seconds": 312,
"scraped_at": "2026-06-02T00:00:00.000Z"
}

charged_events equals the number of successfully saved unique rows.


⚙️ Filters

All filters apply after extraction so visible fields can be evaluated accurately. Filtered-out rows are not pushed and not charged.

FilterEffect
datePostedany / past_24h / past_week / past_month. Enforced at LinkedIn where stable, else text filter.
remoteModeany / remote / hybrid / onsite. Matched against workplace type, remote signal, title, location, and description.
includeRecruiterVisibleOnlyKeep only jobs where public recruiter name or profile URL is visible.
requireSalaryVisibleKeep only jobs with explicit visible salary text.
deduplicateDrop duplicates across inputs by job ID / canonical URL (recommended ON).

🚧 Limitations (V1)

  • Public guest data only: no login, cookies, or member-only content. Some fields (employment type, seniority, industries, applicants, description, apply URL, recruiter info) come from the job detail page and only populate when includeDescription (or a recruiter/salary filter) triggers a detail visit.
  • Recruiter fields are best-effort and sparse: LinkedIn's public guest pages rarely expose recruiter name/profile. When absent, recruiter_visibility is not_visible and the recruiter fields are null. The actor never visits profiles and never logs in.
  • salary_text is kept as raw text (no min/max/currency split) and is only present when LinkedIn shows it; salary_visible reflects that.
  • No email/phone enrichment, full recruiter-profile scraping, company-website crawling, or AI scoring.
  • LinkedIn guest pagination tops out around ~1,000 results per search source; split broad searches into narrower queries for more coverage.
  • maxResults caps saved unique rows across the whole run (not per query); range 1–5000.

❓ FAQ

Do I need a LinkedIn account or cookies? No. The actor only uses LinkedIn's public guest jobs endpoints.

Why are recruiter fields usually empty? Recruiter name/profile are only captured when LinkedIn shows them in the public job HTML, which is uncommon. The actor does not log in or visit profiles, so when the info isn't public the fields stay null / not_visible.

Can I paste a direct job URL? Yes — put https://www.linkedin.com/jobs/view/{id} URLs in startUrls. Each is fetched as a single job and tagged input_type: "job_url".

Can I export to CSV? Yes — every field is flat (no nested objects). Use Apify's CSV / Excel export, or call the dataset API with format=csv.

Will I get blocked? The actor uses conservative concurrency, realistic headers, session rotation, and retry/backoff. Default Apify Proxy is sufficient for typical small/medium runs. For large runs, split searches and/or supply your own proxy provider.


🛠️ Technical notes

  • Stack: Node.js 22 · Apify SDK 3 · Crawlee CheerioCrawler · Cheerio + native fetch. No browser.
  • Endpoints: LinkedIn public guest seeMoreJobPostings (search) and jobPosting (detail).
  • Concurrency: min=1, max=5 (conservative; tune after real runs).
  • Memory: 1 GB min · 2 GB default · 4 GB max.
  • Proxy: Apify Proxy enabled by default; custom configs accepted; Apify Residential rejected at startup.