LinkedIn Scraper - Jobs, Profiles, Posts & Companies
Pricing
from $1.00 / 1,000 results
LinkedIn Scraper - Jobs, Profiles, Posts & Companies
Extract LinkedIn jobs, profiles, posts, and company data across supported countries. Filter jobs by location, employer, seniority, and date. Pay per delivered row plus a small start fee.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
kane liu
Maintained by CommunityActor stats
4
Bookmarked
46
Total users
5
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
LinkedIn Scraper
Export LinkedIn jobs, posts, profiles, and organizations as structured rows for hiring research and analysis.
- Job titles, employers, locations, descriptions, and disclosed salaries.
- Company, industry, seniority, date, and workplace filters.
- Direct job URLs, job IDs, post URLs, and organization targets.
- Optional additional profile and recent-post rows.
- $1 per 1,000 delivered rows on the Free plan, plus a small start fee.
What does LinkedIn Scraper do?
LinkedIn Scraper collects information available from LinkedIn pages and saves one entity per dataset row. Job search supports the country choices in the form, including the United States, United Kingdom, Canada, Germany, India, and Japan, plus free-text locations.
- Jobs: search with
keyword, scope an employer withcompany, or supplydetailUrlsorjobIds. - Posts: supply
postUrlsfor text and published engagement counts. - Profiles and companies: use
profileUrls; useorgUrlsfor companies, schools, or showcase pages. - Discovery: use
discoverKeywordordiscoverSeedsto find profile and company targets. - Additional rows:
enrichProfilesis off by default. Enabling it can add profile/company rows to job searches or up to five recent posts for a profile. Each added row costs the same and shares that input's row limit.
What data can you extract from LinkedIn?
Every row has rowType, a stable id, and scrapedAt. Fields depend on the target and what LinkedIn exposes. Discovery returns the corresponding profile, organization, or post rows, not a guaranteed separate discovery summary.
Job rows (rowType=job)
| Field | Description | Example |
|---|---|---|
jobId | Posting identifier | 4012345678 |
jobTitle | Role title | Python Developer |
companyName | Employer name | Example Company |
companyUrl | LinkedIn employer page | https://www.linkedin.com/company/example-company |
location | Advertised job location | London, England |
jobUrl | Posting URL | https://www.linkedin.com/jobs/view/4012345678 |
postedAt | Posting date when available | 2026-10-20 |
jobDescription | Description with details enabled | Build data applications. |
employmentType | Published employment type | FULL_TIME |
experienceLevel | Published seniority | Associate |
jobFunction | Published function | Engineering |
industry | Published industry | Software Development |
salary | Disclosed amount, currency, period | GBP 60000-80000 YEAR |
isRemote | Remote signal; unknown stays null | true |
workplaceType | Published workplace category | TELECOMMUTE |
skills | Keywords matched in description, not verified qualifications | ["Python", "SQL"] |
easyApply | Easy Apply availability when shown | true |
applyUrl | Application link when shown | https://example.com/jobs/apply |
applicantsCount | Exact count; bounds stay null | 25 |
datePosted | Date published in posting details | 2026-10-20 |
validThrough | Published expiry, when available | 2026-11-20 |
externalId | Your supplied database identifier | record-001 |
emails | Public employer emails; not verified inboxes | [] |
address | Employer address or job-location fallback | {"locality": "London"} |
geo | Published job coordinates, not headquarters | {"lat": null, "lng": null} |
web | Employer website and available social links | {"website": "https://example.com", "socials": []} |
leadAbsences | Explanations for missing contact fields | {} |
Post rows (rowType=post)
| Field | Description | Example |
|---|---|---|
postUrl | Source post URL | https://www.linkedin.com/posts/example-activity-1234567890123456789 |
postText | Published text | Our team is hiring. |
author | Author information | {"name": "Jane Doe"} |
datePublished | Publication date | 2026-10-20 |
reactionCount | Published reactions | 12 |
commentCount | Published comment count | 2 |
repostCount | Published repost count | 1 |
Profile rows (rowType=profile)
| Field | Description | Example |
|---|---|---|
profileUrl | Source profile | https://www.linkedin.com/in/jane-doe |
name | Display name | Jane Doe |
headline | Professional headline | Data Engineer |
about | Public introduction | Building data applications. |
experiences | Visible work history | [] |
education | Visible education | [] |
followerCount | Count when shown | 100 |
Organization rows (rowType=org)
| Field | Description | Example |
|---|---|---|
orgName | Organization name | Example Company |
orgGuestUrl | Source organization page | https://www.linkedin.com/organization-guest/company/example-company |
entity | Organization page type | company |
website | External website | https://example.com |
employeeCount | Published employee count | 100 |
specialties | Published specialties | ["Software"] |
jobCount | Links found on an organization jobs page, not total vacancies | 9 |
How to scrape LinkedIn
- Open LinkedIn Scraper in Apify Console.
- Fill one target field, such as
keyword. - Set
maxResultsto3for a small first run. - Click Start and wait for completion.
- Download the dataset or read its rows through the API.
Empty input starts an example search for python developer, limited to three rows. This is a billed run, not a free preview. A target field selects what to collect automatically; there is no mode field to fill. Prefer one target type per run.
Keyword search
Fill keyword; add country and location. scrapeDetails=false skips job-description enrichment. A location alone is not a search target.
Employer jobs
Use a company ID or company page URL in company, or a numeric companyId. Set keyword to an empty string for an employer-only search.
Known jobs
Use detailUrls or jobIds; these can be combined. Full LinkedIn job URLs are preferable when available. externalIds follows the order of URLs, then IDs.
Posts
Use postUrls with LinkedIn post URLs or activity URNs. Available text and counts vary by post.
Profiles and company pages
Use profileUrls with /in/ or /company/ URLs. Recent posts require enrichProfiles=true and enough remaining row allowance.
Organizations
Use orgUrls, for example company:microsoft or school:stanford-university. These return organization records; organization jobs pages are not a substitute for complete employer job search.
Discovery
Use discoverKeyword or seed tokens such as company:microsoft in discoverSeeds. Set a small discoverLimit; candidates may be unavailable or unrelated, so review the returned rows.
What to fill in
| Field | What to enter | Default |
|---|---|---|
keyword | One job title or search phrase | Sample: python developer |
detailUrls | LinkedIn HTTPS job URLs | Empty |
jobIds | Job posting IDs | Empty |
company | Company IDs or URLs, comma-separated | Empty |
companyId | One numeric employer ID | Empty |
postUrls | Post URLs or activity URNs | Empty |
profileUrls | Profile or company URLs | Empty |
orgUrls | Organization URLs or typed slug tokens | Empty |
location | City, state, or region | Empty |
country | Form country code, such as gb, or remote | Any |
industry | Form option, such as software | Any |
jobFunction | Form option, such as engineering | Any |
jobType | F full-time, P part-time, C contract, T temporary, I internship, V volunteer, O other | Any |
datePosted | r86400 day, r604800 week, r2592000 month | Any |
experienceLevel | 1 internship through 6 executive, as labeled in the form | Any |
remoteFilter | 1 on-site, 2 remote, 3 hybrid | Any |
easyApplyOnly | Only Easy Apply jobs | false |
under10Applicants | Jobs marked below ten applicants | false |
sortBy | relevance or recent | Relevance |
maxResults | Rows per input, from 1 to 1,000 | 70; form prefill 3 |
scrapeDetails | Include available job details | true |
enrichProfiles | Add separately billed related rows | false |
discoverKeyword | Profile/company discovery phrase | Empty |
discoverSeeds | Tokens such as in:jane-doe | Empty |
discoverLimit | Discovery candidate limit, 1–200 | 20 |
offlineCorpus | Include indexed discovery candidates | false |
liAtCookie | Optional authorized LinkedIn session for profile fields; not required for jobs. Using your own session cookie is at your own risk and subject to LinkedIn's terms; the Actor works without it for public data. | Empty |
externalIds | Your IDs corresponding to direct job inputs | Empty |
rowLayout | Keep one entity per row | rows |
Keyword search
{"keyword": "python developer", "country": "gb", "datePosted": "r604800", "maxResults": 3}
Employer jobs
{"companyId": "1035", "keyword": "", "maxResults": 3}
Known jobs
{"jobIds": ["4012345678"], "externalIds": ["record-001"], "maxResults": 1}
Posts
{"postUrls": ["urn:li:activity:7133147405666959360"], "maxResults": 1}
Profiles
{"profileUrls": ["https://www.linkedin.com/in/jane-doe"], "maxResults": 1}
Organizations
{"orgUrls": ["company:microsoft"], "maxResults": 1}
Discovery
{"discoverKeyword": "data engineering", "discoverLimit": 3, "maxResults": 3}
The profile URL is a placeholder; replace it with your target.
maxItems and limit are aliases for maxResults; query maps to keyword, and startUrls to detailUrls. Close field-name misspellings are corrected; other unknown fields are ignored with a note. Invalid filter choices are ignored rather than stopping collection. Check INPUT_REPORT in the default key-value store to see how each run interpreted the input.
Invalid targets stop before row charges with INVALID_INPUT: <field> — <how to fix>. The start fee still applies. datePosted is a recency filter, not an automatically expanding date window.
Output example
Illustrative job row; actual values and field availability depend on the posting:
{"rowType": "job","id": "4012345678","jobId": "4012345678","jobTitle": "Python Developer","companyName": "Example Company","location": "London, England","jobUrl": "https://www.linkedin.com/jobs/view/4012345678","jobDescription": "Build Python data applications.","salary": null,"isRemote": null,"easyApply": null,"applicantsCount": null,"skills": ["Python"],"scrapedAt": "2026-10-24T08:00:00Z"}
Export the dataset as JSON, CSV, Excel, XML, RSS, or an HTML table.
Why use this LinkedIn scraper?
- Row-based billing: after the start fee, charges apply to delivered rows, not pages tried.
- Partial results: rows already saved remain available after a stop. Collection interrupted by a deadline can deliver the rows gathered before it stopped.
- Inspect failures:
ERROR_SUMMARYexplains failures;RUN_SUMMARYcan include partial-result reasons and warnings even when a run succeeds. - Missing stays missing: undisclosed salaries and unavailable counts are not invented. Job skills are explicitly derived from description text.
- Several inputs: URL and ID arrays let you submit multiple targets together.
- No proxy setup: you do not need to set up proxies.
How much does it cost to scrape LinkedIn?
Pricing is pay-per-event. At the default 512 MB memory, starting a run incurs one $0.00005 start event. The start event counts once per GB, with a minimum of one event. Platform usage is included in these prices.
| Apify plan | Start fee at 512 MB | Price per row | Price per 1,000 rows |
|---|---|---|---|
| Free | $0.00005 | $0.001 | $1.00 |
| Starter | $0.00005 | $0.001 | $1.00 |
| Scale | $0.00005 | $0.001 | $1.00 |
| Business | $0.00005 | $0.001 | $1.00 |
maxResults applies to each input, defaults to 70, and accepts up to 1,000. Larger requests are collected in parts of at most 70 rows. All row types for that input share its allowance. Free Apify plan runs are capped at 200 rows, with ten total runs of this Actor. Paid plans remove that ten-run cap.
The whole run stops at your Maximum cost per run (maxTotalChargeUsd in the API). Limits are ceilings, not guarantees of enough matching data.
Example: five delivered rows at 512 MB cost 5 × $0.001 + $0.00005 = $0.00505, on any listed plan.
What happens when the run timeout is too short
If collection needs longer than your timeout, the run can pause automatically instead of failing. Its status becomes ABORTED with the message "Queued on the collection backend; this run will resume automatically when results are ready (about N s)."
When ready, the same run resumes and writes to the same dataset, finishing as SUCCEEDED when delivery succeeds. Continued delivery can show "Resumed: delivering N rows." Previously delivered rows are skipped, so they are not delivered or charged twice. No manual restart is needed for this pause.
This can happen at most three times per run. Keep the default 1,800-second timeout to reduce interruptions. Actual collection failures can still fail a run.
Synchronous endpoints (run-sync, run-sync-get-dataset-items) wait at most 300 seconds and can return an empty dataset during a pause. For longer work, start asynchronously and read results after SUCCEEDED, or use an ACTOR.RUN.SUCCEEDED webhook. Calls that wait for completion can also return at the temporary ABORTED state.
Use with AI agents and the API
Apify MCP server
Add this remote MCP server in Claude, ChatGPT, Cursor, VS Code, or another compatible client:
https://mcp.apify.com?tools=lentic_clockss/linkedin-jobs-scraper
Sign in with Apify through OAuth, or send Authorization: Bearer <YOUR_APIFY_TOKEN>. The tool starts a run and returns run and dataset IDs; read rows with get-dataset-items. For clients without remote support, run npx @apify/actors-mcp-server --tools lentic_clockss/linkedin-jobs-scraper with APIFY_TOKEN configured.
Example prompt: "Find three data engineer jobs in London posted this week, including salary when disclosed."
Apify API
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("lentic_clockss/linkedin-jobs-scraper").call(run_input={"keyword": "data engineer", "country": "gb", "maxResults": 3})if run["status"] == "SUCCEEDED":for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('lentic_clockss/linkedin-jobs-scraper').call({keyword: 'data engineer', country: 'gb', maxResults: 3,});if (run.status === 'SUCCEEDED') {const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);}
For asynchronous HTTP, send POST https://api.apify.com/v2/acts/lentic_clockss~linkedin-jobs-scraper/runs with JSON input and an Authorization: Bearer header. After success, fetch GET https://api.apify.com/v2/datasets/<datasetId>/items?format=json.
Integrations
Use the Integrations tab for Google Sheets, Make, Zapier, n8n, Slack, Airtable, or webhooks. Apify Schedules can repeat a saved input.
FAQ
Is it legal to scrape LinkedIn?
Public availability is not permission for every use. You are responsible for LinkedIn's terms and applicable data-protection law. Processing personal data requires a lawful basis; limit collection and retention to your purpose.
Why did my run end as ABORTED?
The automatic pause described above uses ABORTED temporarily. Check the status message; a manual abort or unrelated interruption is not necessarily resumable.
How many results can I get?
Up to 1,000 rows per input, subject to available matches, the run's cost limit, and Free-plan caps. Added profile or post rows reduce the remaining allowance.
Why are some fields empty?
LinkedIn may omit them, or a detail page may be unavailable. Salary is only returned when disclosed. Applicant bounds such as "Over 200" are not exact counts and remain null.
Do I need a LinkedIn account?
Not for public job search. Optional profile enrichment with liAtCookie uses your authorized session and cannot guarantee access to restricted fields. Never share session values in support requests.
Can I monitor one company?
Yes. Supply its LinkedIn URL or ID in company, or use companyId. Compare jobId values in your own storage to identify repeats. Missing rows alone do not prove vacancies closed.
Can I get only remote jobs?
Set remoteFilter to 2. Choosing country=remote supplies that filter when no workplace filter is already set. Inspect each returned job's location.
Limitations
- Results are not a complete LinkedIn census; narrow filters and unavailable pages can reduce counts.
- Location filtering is not a strict geographic boundary.
- Phone and hiring-contact extraction are not implemented. Public employer emails are neither guaranteed nor verified for deliverability or outreach suitability.
- Employer
addressand jobgeocan refer to different places; city-only addresses do not establish a headquarters street address. - Profile history, recent posts, and engagement counts can be incomplete. Discovery candidates are not guaranteed matches.
Related scrapers
More job board and freelance marketplace scrapers from the same publisher:
- Indeed Scraper
- Upwork Scraper
- Freelancer.com Scraper
- Glassdoor Scraper
- SEEK Scraper
- Bayt Scraper
- Fiverr Scraper
Browse all of our scrapers at apify.com/lentic_clockss.
Support
Report problems or request a field through the Issues tab of this Actor's page. Include the run ID and input, with credentials removed.