LinkedIn Search Jobs Scraper & Company Insights
Pricing
from $5.99 / 1,000 results
LinkedIn Search Jobs Scraper & Company Insights
Scrape LinkedIn job search results with company insights, including job titles, locations, employment types, posting dates, company names, industries, sizes, and URLs. Analyze hiring trends, research employers, identify prospects, and build targeted recruitment and B2B lead lists.
Pricing
from $5.99 / 1,000 results
Rating
0.0
(0)
Developer
Scrapier
Maintained by CommunityActor stats
0
Bookmarked
14
Total users
0
Monthly active users
3 days ago
Last modified
Categories
Share
LinkedIn Jobs Scraper — Company Profiles & Salary Insights
LinkedIn Jobs Scraper — Company Profiles & Salary Insights searches LinkedIn's public job listings by keyword, location, or company URL, and attaches each job's employer company profile and any structured salary or requirements data LinkedIn has published for that posting. Every run returns job records, company-profile records, and salary insights as clean, structured JSON — ready to pass directly to an LLM, index into a vector store, or feed a monitoring pipeline. Results save to the dataset live, so results are usable well before a large run finishes.
🔍 What is LinkedIn Jobs Scraper — Company Profiles & Salary Insights?
It's a query-driven LinkedIn job search actor: give it a keyword, a keyword, location string, a full job search URL, a company profile URL, or a direct job URL/ID, and it returns every matching job posting it can discover. What sets this variant apart is that it doesn't stop at the job card — for each unique employer it fetches that company's own public LinkedIn page (industry, size, headquarters, founded year, followers), and for each job it reads LinkedIn's own structured salary/requirements data block when one exists. No LinkedIn account or login is required; every page fetched is a publicly accessible, logged-out guest page.
- Job listings — title, company, location, description, seniority, employment type, job function, industries, posted time, applicant count
- Company profiles — industry, employee-count range, headquarters, organization type, founded year, follower count, tagline, website (one fetch per unique employer per run, cached)
- Salary & requirements insights — salary range, absolute posted/expiry dates, employment type, job location with coordinates, months of experience, education tier
- Company-scoped search — a
linkedin.com/company/...URL is resolved to that company's real numeric organization ID before searching, so results are actually limited to that employer's own openings - Query controls — sort by relevance or recency, per-input job cap, independent on/off toggles for company enrichment and salary insights
📊 What data can you get with this scraper?
Every run can return up to three result types per job, depending on which toggles are enabled:
| Result Type | Extracted Fields | Primary Use Case |
|---|---|---|
| Job listing | id, title, company, location, postedTimeAgo, numberOfApplicants, description, criteria (seniority level, employment type, job function, industries), link, job.link | Core job search feed, ATS/CRM import |
| Company profile | companyProfile.numericOrgId, industry, companySize, employeeCountRange.start/end, headquarters, organizationType, foundedYear, followerCount, tagline, website | Employer research, B2B lead qualification |
| Salary & requirements insights | salaryInsights.baseSalary.currency/minValue/maxValue/unitText, datePosted, validThrough, employmentType, industry, jobLocation.address, jobLocation.latitude/longitude, monthsOfExperience, educationCredentialCategory | Compensation benchmarking, requirement filtering |
Company profile & salary insights
Both of these are fetched independently of the job card itself. The company profile comes from the employer's own linkedin.com/company/<slug>/ guest page — parsed once per unique company per run and cached, so a search that returns 200 jobs at the same 12 employers only fetches 12 company pages, not 200. The salary/requirements insights come from the job's own JSON-LD JobPosting structured-data block, which only renders on the job's exact canonical slugged URL — so this actor resolves that canonical URL first, from the search result card when available or from the job's own page otherwise, then reads the block. Coverage on salary is genuinely partial: LinkedIn does not publish this block on every posting, and when it's absent the fields come back null, never guessed or backfilled from the description text.
{"companyProfile": {"numericOrgId": "30898036","industry": "Software Development","companySize": "501-1,000 employees","employeeCountRange": { "start": 501, "end": 1000 },"headquarters": "San Francisco, CA","organizationType": "Privately Held","foundedYear": 2013,"followerCount": 1234567,"tagline": "Write, plan, and get organized.","website": "https://www.notion.so"},"salaryInsights": {"baseSalary": { "currency": "USD", "minValue": 120000, "maxValue": 180000, "unitText": "YEAR" },"datePosted": "2026-07-28","validThrough": "2026-08-28","monthsOfExperience": 24,"educationCredentialCategory": "bachelor degree"}}
Job listing details
Each job record also carries the standard listing content: full description text, the criteria list LinkedIn shows on the card (seniority level, employment type, job function, industries), posted time and applicant count as displayed, and both a company link and a job link. The nested job object repeats id, title, company, and location alongside the job's own resolved link — useful when you want a flat reference object independent of the enrichment fields.
Why not build this yourself?
LinkedIn does not offer a general-purpose, self-serve public API for searching job postings — its Talent Solutions and Recruiter System Connect APIs are partner-gated, requiring a business relationship with LinkedIn rather than an API key you can request and use immediately. Building a scraper yourself instead means owning the query-surface parsing (LinkedIn changes its search HTML and guest-page markup without notice), the anti-bot escalation (retry/backoff logic, realistic headers, optional residential proxies), and the canonical-URL resolution needed to reach the structured salary block at all. This actor handles all three, and re-fetches per unique company rather than per job to keep the request count down. If you already hold approved LinkedIn Talent Solutions partner access, use that API. If you need ad hoc, keyword- or company-scoped job search with employer and salary enrichment attached, this actor is the faster path.
🧭 How to scrape LinkedIn jobs with this scraper
- Open this actor on the Apify Store and click Try for free (or Run, if you've already added it to your account).
- Add one or more entries to
startUrls— a keyword, akeyword, locationstring, a full LinkedIn job search URL, a company profile URL, or a direct job URL/ID. - Set
maxJobs(per input) andsortOrder(relevantorrecent). LeaveenrichCompanyProfileandextractSalaryInsightson if you want the enrichment data, or turn either off for a faster, lighter run. - Start the run from the Apify Console, the API, or the
apify-clientSDK. - Download results as JSON, CSV, or Excel from the run's dataset, or stream them via the API as they're written.
How to run multiple searches in one job
startUrls accepts one item per line, and each line can be a different input type — mix keyword searches, company URLs, and direct job URLs/IDs in the same run. The actor processes each input in turn, deduplicates jobs by ID across all of them, and writes every unique result to the same dataset.
⬇️ Input
All input is set through the six fields below (.actor/actor.json input schema). Only startUrls is required.
| Parameter | Required | Type | Constraints | Description |
|---|---|---|---|---|
startUrls | Yes | array of strings | — | Keywords, keyword, location, keyword1|keyword2, location, a full LinkedIn job search URL, a company profile URL (e.g. linkedin.com/company/notion), or a direct job URL/ID. One item per line. |
sortOrder | No | string | default "relevant"; enum "relevant", "recent" | Sort by relevance or by most recent postings. |
maxJobs | No | integer | default 10; min 1; max 10000 | Maximum jobs to scrape per input. |
enrichCompanyProfile | No | boolean | default true | Fetch and attach each unique employer's company profile. |
extractSalaryInsights | No | boolean | default true | Fetch and attach each job's structured salary/requirements data. |
proxyConfiguration | No | object | default {"useApifyProxy": false} | Optional Apify Proxy. Direct requests are used unless enabled. |
⚠️ maxJobs allows up to 10,000, but real delivery is capped at roughly 1,000 jobs per input. Job discovery for a single search input stops after 40 result pages (25 jobs per page), which is a fixed limit in this actor's search loop — a higher maxJobs value will not push past that ceiling for one input. To collect more, split the search across more specific keyword or location inputs.
Example input:
{"startUrls": ["software engineer, United States","https://www.linkedin.com/company/notion"],"sortOrder": "relevant","maxJobs": 20,"enrichCompanyProfile": true,"extractSalaryInsights": true,"proxyConfiguration": {"useApifyProxy": false}}
Common pitfall: only a full linkedin.com/company/<slug> URL triggers company-scoped resolution. A bare company name typed as plain text (no URL) is parsed as a keyword and searched across all jobs mentioning that name, not scoped to that employer's own postings — if you need company-scoped results, always pass the company profile URL, not just its name.
⬆️ Output
Results are typed, normalized JSON with a consistent schema across runs, written to the dataset one job at a time as it's collected (live saving) rather than at the end of the run. Export from the Apify Console as JSON, CSV, Excel, XML, or RSS, or pull it through the API/apify-client.
Scraped results
[{"id": "4333046374","title": "Software Engineer","company": "Notion Labs, Inc.","location": "San Francisco, CA","postedTimeAgo": "1 day ago","numberOfApplicants": "Over 200 applicants","description": "Notion is on a mission to make it possible for every person, team, and company to tailor their software to the problems they have...","criteria": [{ "title": "Seniority level", "value": "Mid-Senior level" },{ "title": "Employment type", "value": "Full-time" },{ "title": "Job function", "value": "Engineering" },{ "title": "Industries", "value": "Software Development" }],"link": "https://www.linkedin.com/company/notion","job": {"id": "4333046374","link": "https://www.linkedin.com/jobs/view/software-engineer-at-notion-4333046374","title": "Software Engineer","company": "Notion Labs, Inc.","location": "San Francisco, CA"},"companyProfile": {"numericOrgId": "30898036","industry": "Software Development","companySize": "501-1,000 employees","employeeCountRange": { "start": 501, "end": 1000 },"headquarters": "San Francisco, CA","organizationType": "Privately Held","foundedYear": 2013,"followerCount": 1234567,"tagline": "Write, plan, and get organized.","website": "https://www.notion.so"},"salaryInsights": {"baseSalary": { "currency": "USD", "minValue": 120000, "maxValue": 180000, "unitText": "YEAR" },"datePosted": "2026-07-28","validThrough": "2026-08-28","employmentType": "FULL_TIME","industry": "Software Development","jobLocation": {"address": { "country": "US", "locality": "San Francisco", "region": "CA" },"latitude": 37.7749,"longitude": -122.4194},"monthsOfExperience": 24,"educationCredentialCategory": "bachelor degree"},"scrapedAt": "2026-08-04T12:00:00Z"},{"id": "4331120987","title": "Product Manager, Growth","company": "Notion Labs, Inc.","location": "Remote (United States)","postedTimeAgo": "3 days ago","numberOfApplicants": "89 applicants","description": "We're looking for a Product Manager to own our growth funnel...","criteria": [{ "title": "Seniority level", "value": "Mid-Senior level" },{ "title": "Employment type", "value": "Full-time" }],"link": "https://www.linkedin.com/company/notion","job": {"id": "4331120987","link": "https://www.linkedin.com/jobs/view/product-manager-growth-at-notion-4331120987","title": "Product Manager, Growth","company": "Notion Labs, Inc.","location": "Remote (United States)"},"companyProfile": {"numericOrgId": "30898036","industry": "Software Development","companySize": "501-1,000 employees","employeeCountRange": { "start": 501, "end": 1000 },"headquarters": "San Francisco, CA","organizationType": "Privately Held","foundedYear": 2013,"followerCount": 1234567,"tagline": "Write, plan, and get organized.","website": "https://www.notion.so"},"salaryInsights": {"baseSalary": null,"datePosted": null,"validThrough": null,"employmentType": null,"industry": null,"jobLocation": null,"monthsOfExperience": null,"educationCredentialCategory": null},"scrapedAt": "2026-08-04T12:00:41Z"},{"id": "4329887210","title": "Backend Engineer, Infrastructure","company": "Acme Robotics Inc.","location": "Austin, TX","postedTimeAgo": "6 hours ago","numberOfApplicants": "24 applicants","description": "Acme Robotics is hiring a Backend Engineer to build our infrastructure platform...","criteria": [{ "title": "Seniority level", "value": "Entry level" },{ "title": "Employment type", "value": "Full-time" },{ "title": "Industries", "value": "Robotics Engineering" }],"link": "https://www.linkedin.com/company/acme-robotics","job": {"id": "4329887210","link": "https://www.linkedin.com/jobs/view/backend-engineer-infrastructure-at-acme-robotics-4329887210","title": "Backend Engineer, Infrastructure","company": "Acme Robotics Inc.","location": "Austin, TX"},"companyProfile": {"numericOrgId": "9012345","industry": "Robotics Engineering","companySize": "51-200 employees","employeeCountRange": { "start": 51, "end": 200 },"headquarters": "Austin, TX","organizationType": "Privately Held","foundedYear": 2019,"followerCount": 8420,"tagline": "Robots for the last mile.","website": "https://acmerobotics.example"},"salaryInsights": {"baseSalary": { "currency": "USD", "minValue": 95000, "maxValue": 130000, "unitText": "YEAR" },"datePosted": "2026-08-03","validThrough": "2026-09-03","employmentType": "FULL_TIME","industry": "Robotics Engineering","jobLocation": {"address": { "country": "US", "locality": "Austin", "region": "TX" },"latitude": 30.2672,"longitude": -97.7431},"monthsOfExperience": 12,"educationCredentialCategory": null},"scrapedAt": "2026-08-04T12:01:15Z"}]
How can I use the data extracted with this scraper?
- 🎯 Recruiters and talent sourcing teams — pull open roles at target companies with
companyProfile.industryandcompanyProfile.companySizealready attached, so shortlists don't need a separate employer lookup. - 📊 B2B and lead-generation researchers — treat every unique employer that's actively hiring as a signal: filter by
companyProfile.headquarters,foundedYear, orfollowerCountto prioritize outreach. - 💰 Compensation analysts — collect
salaryInsights.baseSalaryranges by role,jobLocation, andmonthsOfExperienceacross companies for benchmarking, keeping in mind coverage is partial by design. - 🤖 AI engineers and LLM developers — feed the structured JSON straight into a retrieval pipeline or agent: query in, job/company/salary objects out, ready as grounded context for a model without extra parsing.
📈 How do you monitor hiring and compensation trends over time?
Job postings, company follower counts, and published salary ranges all change between runs, and the delta is usually more useful than any single snapshot. Re-running the same startUrls on a schedule turns this actor into a monitoring feed: new job IDs appearing since the last run mean new openings; a job's disappearance from a repeat search (or a salaryInsights.validThrough date in the past) means it's likely closed; a companyProfile.followerCount or companyProfile.employeeCountRange change tracks employer growth over the same period you're tracking hiring.
A practical setup: keep one input per company or keyword you track, run on an Apify schedule (daily or weekly), and diff each new run's dataset against the previous one on id for new/closed postings and on salaryInsights.baseSalary.minValue/maxValue for compensation shifts at the same company. Because company profiles are cached per run rather than persisted across runs, comparing companyProfile fields run-over-run means comparing the dataset's stored values directly, not re-fetching history from LinkedIn. Apify schedules trigger the run automatically; dataset webhooks can push each run's output to your own pipeline as soon as it finishes.
🔌 Integrate this scraper and automate your workflow
This actor works with any language or tool that can call the Apify API — there's no separate signup or credential flow beyond your Apify account.
REST API with Python
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_API_TOKEN>")run = client.actor("scrapier/linkedin-search-jobs-scraper-and-company-insights").call(run_input={"startUrls": ["software engineer, United States"],"maxJobs": 20,"enrichCompanyProfile": True,"extractSalaryInsights": True,})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["company"], job["salaryInsights"]["baseSalary"])
Scheduled monitoring and delivery
Set up an Apify schedule against this actor's saved task to re-run the same startUrls on a recurring cadence, and attach a dataset or run webhook to push each run's results to your own endpoint as soon as it finishes — no polling required if you configure the webhook.
⚖️ Is it legal to scrape LinkedIn job listings?
Yes — scraping publicly accessible LinkedIn job listings and company pages is generally lawful, because this actor only reads what any logged-out visitor sees, without bypassing a login wall or accessing private data. In hiQ Labs, Inc. v. LinkedIn Corp., 938 F.3d 985 (9th Cir. 2019), the Ninth Circuit held that scraping publicly available LinkedIn data does not violate the Computer Fraud and Abuse Act. Job postings and company profiles are business/organizational data, not personal data about identifiable individuals, so this is primarily a terms-of-service and database-rights question rather than a GDPR/CCPA one — LinkedIn's own Terms of Service restrict automated access, and courts have treated that as a separate contract question from anti-hacking law. Consult your legal team before storing bulk data at scale or using it for a commercial product.
❓ Frequently asked questions
Can I search jobs in a specific location or region?
Yes — pass a structured input in the format keyword, location (or keyword1|keyword2, location) in startUrls, e.g. "data engineer, London, United Kingdom". There's no separate location parameter; location is part of the search string itself, matching how LinkedIn's own job search box works.
How do I sort by most recent postings instead of relevance?
Set sortOrder to "recent". The default, "relevant", sorts by LinkedIn's own relevance ranking; "recent" sorts by posting date, newest first.
How does this scraper handle LinkedIn's anti-bot measures?
It uses randomized delays between requests, realistic browser headers, and automatic retries with exponential backoff (up to 3 attempts) on failed or rate-limited responses. Apify Proxy can be enabled via proxyConfiguration if direct requests start getting blocked; it's off by default.
Does this scraper extract company profile and salary data automatically?
Yes, by default. enrichCompanyProfile (default true) attaches the employer's company profile, and extractSalaryInsights (default true) attaches structured salary/requirements data — both arrive as their own nested objects (companyProfile, salaryInsights) on every job record. Salary data is null on jobs where LinkedIn hasn't published it, which is common; it's never estimated or filled in.
How many jobs does this scraper return per search?
Up to maxJobs (default 10, max 10,000) — but real delivery for a single search input is capped at roughly 1,000 jobs, because job discovery for one input stops after 40 result pages of 25 jobs each. A single job URL or company-scoped search returns however many unique postings LinkedIn's own pagination surfaces within that limit.
How do I monitor a company's hiring or salary trends over time?
Keep a fixed input per company or keyword, run it on an Apify schedule, and compare each new dataset against the previous one on job id (new/closed postings) and on salaryInsights.baseSalary (compensation changes). See "How do you monitor hiring and compensation trends over time?" above for the full workflow.
Does this scraper work with Claude, ChatGPT, and AI agent frameworks?
It's callable as a standard HTTP endpoint through the Apify API, so any agent framework that can issue an HTTP request or call a Python/JS SDK can trigger a run and read the resulting JSON — the agent gets grounded job, company, and salary data to reason over instead of relying on the model's own (likely outdated) knowledge.
Can I use this scraper without managing proxies or a LinkedIn account?
Yes. It runs against LinkedIn's public, logged-out guest pages by default, with no LinkedIn login required and no proxy required — Apify Proxy is available as an optional toggle if your specific run starts getting blocked. You only need an Apify account and API token to run it.
💬 Your feedback
Found a bug, or a field that's missing from your dataset? Let us know through the actor's Issues tab on the Apify Store, or message Scrapier support directly. Feedback like this drives the next update.