Linkedin Company Jobs Scraper avatar

Linkedin Company Jobs Scraper

Pricing

from $5.00 / 1,000 results

Go to Apify Store
Linkedin Company Jobs Scraper

Linkedin Company Jobs Scraper

Bulk scrape public job listings from lists of LinkedIn Company pages. Bypasses guest limits and data obfuscation (*****) to retrieve hundreds of clean results per company. Features smart proxy rotation and automated batch processing to scale your data collection.

Pricing

from $5.00 / 1,000 results

Rating

0.0

(0)

Developer

Gyanendra Thakur

Gyanendra Thakur

Maintained by Community

Actor stats

4

Bookmarked

118

Total users

35

Monthly active users

13 days ago

Last modified

Categories

Share

Collect, filter, enrich, and monitor public jobs from LinkedIn company pages.

This Apify Actor is designed for people who need dependable company-level hiring data without maintaining their own scraper. Add one or more public LinkedIn company URLs, choose a run profile, and receive clean job records in an Apify Dataset. Advanced controls are available when you need tighter filtering, predictable runtime, persistent new-job monitoring, or job-detail enrichment.

The Actor uses public LinkedIn company pages and public guest job endpoints. It does not sign in to LinkedIn or access profiles, messages, private pages, or member-only data.

What you can do

  • Scrape one company or up to 100 company pages in a run.
  • Start quickly with Fast, Balanced, or Enriched profiles.
  • Limit results by posting age, keywords, location, remote status, workplace type, employment type, or seniority.
  • Fetch descriptions, applicant text, apply URLs, and other public detail fields.
  • Run scheduled monitoring workflows that emit only newly discovered matching jobs.
  • Choose whether the first monitoring run emits or silently stores its baseline.
  • Control pages, total results, request attempts, retries, pacing, detail concurrency, and whole-run duration.
  • Continue past an unavailable company or stop immediately.
  • Keep partial job results when the configured run-time budget is reached.
  • Export jobs as JSON, CSV, Excel, XML, HTML, or through the Apify Dataset API.

Quick start

  1. Open the Actor's Input tab.
  2. Add at least one URL such as https://www.linkedin.com/company/google.
  3. Leave Balanced selected for a normal discovery run.
  4. Optionally add filters.
  5. Start the Actor.
  6. Open Output > Job records to inspect or export the dataset.
  7. Open Run summary when you need counts, failures, stop reasons, or the resolved configuration.

Minimal API input:

{
"companyUrls": ["https://www.linkedin.com/company/google"],
"runProfile": "balanced"
}

Choose a run profile

Profiles provide defaults. Any advanced field included in the input overrides the selected profile.

ProfileBest forDescriptionsJobs/companyRequest budgetRun budgetDetail concurrency
fastQuick discovery and inexpensive testsNo501005 minutes1
balancedMost regular scraping workflowsNo5030015 minutes2
enrichedResearch requiring descriptions and detail metadataYes5050030 minutes3
customFully controlled API inputsNo5030015 minutes2

For an unfiltered run, the Actor derives a conservative page allowance from maxJobs instead of automatically scanning the profile's full page ceiling. Selective filters and monitoring retain the wider profile allowance. An explicit maxPagesPerCompany always wins.

Input reference

Companies

InputTypeDefaultBehavior
companyUrlsstring[]RequiredPublic https://www.linkedin.com/company/... URLs. Duplicates, query strings, fragments, and trailing slashes are normalized.

The input form accepts up to 100 unique company URLs. Invalid URLs are rejected before network requests begin.

Profile and enrichment

InputTypeDefaultBehavior
runProfilestringbalancedSelects Fast, Balanced, Enriched, or Custom defaults.
maxJobsintegerProfile valueMaximum jobs that pass all filters per company, from 1 to 2,000.
maxTotalJobsinteger1,000Hard dataset-row cap across the entire run. Explicit maxJobs can raise it.
scrapeDescriptionbooleanProfile valueFetches descriptions and public detail fields only for candidates still needed.

Some filters require detail metadata. If remoteFilter, workplaceTypes, employmentTypes, or seniorityLevels is active, the Actor fetches job details even when scrapeDescription is false. In that case, metadata is used for filtering but description fields remain unrequested.

Date, keyword, and location filters

InputTypeDefaultBehavior
postedWithinDaysinteger0Keeps jobs posted in the last N days. 0 disables the date filter.
includeJobsWithUnknownDatebooleantrueKeeps records whose public card has no valid posting date.
keywordIncludestring[][]Terms matched case-insensitively against title and location.
keywordMatchModestringanyRequires any or all include terms.
keywordExcludestring[][]Rejects a job when any term appears in title or location.
locationIncludestring[][]Requires the raw location to contain at least one value.
locationExcludestring[][]Rejects the raw location when it contains any value.

Exclusion always wins. The Actor rejects an input when the same normalized term is present in both an include and exclude list because that configuration cannot produce an intuitive result.

Detail metadata filters

InputTypeDefaultBehavior
remoteFilterstringallAccepts all, remote, or nonRemote.
workplaceTypesstring[][]Exact match against Remote, Hybrid, or On-site.
employmentTypesstring[][]Exact match against public values such as Full-time, Contract, or Internship.
seniorityLevelsstring[][]Exact match against public LinkedIn seniority values.
includeJobsWithUnknownMetadatabooleantrueControls whether jobs missing a selected detail field pass that filter.

LinkedIn does not publish every metadata field on every job. For strict datasets, set includeJobsWithUnknownMetadata to false. For broader discovery, leave it enabled.

Monitoring

InputTypeDefaultBehavior
newJobsOnlybooleanfalseEmits only matching job keys not already stored for this company and namespace.
monitoringStoreIdstringNamed persistent storeSelect an existing Apify key-value store. When omitted, the Actor uses or creates linkedin-company-scraper-monitoring.
monitoringNamespacestringdefaultIsolates schedules or filter sets sharing one monitoring store.
monitoringFirstRunPolicystringemitemit returns and stores the baseline. storeOnly stores it without writing baseline jobs to the dataset.
resetMonitoringbooleanfalseClears state for the requested companies and namespace before scraping.

Monitoring is keyed by company and namespace. Use a different namespace whenever two schedules should have independent history, for example:

  • engineering_daily
  • sales_us_weekly
  • all_jobs_archive

The Actor updates monitoring state only after a company completes successfully. If a company fails or the whole-run budget interrupts that company, its incomplete pass does not become the new baseline.

State uses Apify-safe record keys such as monitoring_daily_engineering_1441_job_keys and monitoring_daily_engineering_1441_last_run.

Reliability and cost controls

InputTypeProfile defaultBehavior
maxPagesPerCompanyintegerAutomatic, max 100Hard company page limit. Unfiltered runs derive a smaller allowance from maxJobs.
maxRequestsPerRuninteger100, 300, 500Hard attempt budget covering company, listing, detail, and retry requests.
maxRunTimeSecondsinteger300, 900, or 1,800Whole-run budget. The Actor reserves a shutdown buffer and writes partial-run records.
requestTimeoutSecondsinteger30, 45, or 60Per-request timeout.
maxRequestRetriesinteger2 or 3Bounded retries after transient request failures.
retryDelaySecondsinteger1 or 2Initial backoff delay. Later retries use exponential backoff with jitter.
requestDelayMillisinteger750 to 1,250Randomized pacing before public LinkedIn requests.
detailConcurrencyinteger1 to 3Parallel job-detail requests, capped at 5.
failurePolicystringcontinueContinue to other companies or stop with failFast.
proxyConfigurationobjectApify Residential ProxyStandard Apify proxy editor. The Actor respects the supplied setting instead of forcing a proxy group.

The Actor stops pagination on empty pages, exact repeated page signatures, explicit page limits, request limits, result limits, or the whole-run time budget. Short pages are not treated as final because LinkedIn can return fewer cards while later pages still exist.

The Actor definition defaults to 1,024 MB of memory and bounds automatic allocation between 512 MB and 2,048 MB. The scraper is HTTP-based and processes companies sequentially, so a 4,096 MB default adds cost without improving extraction quality.

Example inputs

Fast company hiring scan

{
"companyUrls": ["https://www.linkedin.com/company/google", "https://www.linkedin.com/company/microsoft"],
"runProfile": "fast",
"maxJobs": 100,
"postedWithinDays": 30,
"keywordExclude": ["intern"]
}

Enriched recruiting research

{
"companyUrls": ["https://www.linkedin.com/company/tesla-motors"],
"runProfile": "enriched",
"maxJobs": 200,
"postedWithinDays": 14,
"keywordInclude": ["engineer", "developer"],
"keywordMatchMode": "any",
"locationInclude": ["United States", "Remote"],
"employmentTypes": ["Full-time"],
"includeJobsWithUnknownMetadata": false
}

Remote-only jobs

{
"companyUrls": ["https://www.linkedin.com/company/github"],
"runProfile": "balanced",
"remoteFilter": "remote",
"workplaceTypes": ["Remote"],
"postedWithinDays": 30,
"maxJobs": 100
}

Remote and workplace filters trigger detail requests even with the Balanced profile.

Daily new-job monitoring

{
"companyUrls": ["https://www.linkedin.com/company/google", "https://www.linkedin.com/company/anthropicresearch"],
"runProfile": "balanced",
"newJobsOnly": true,
"monitoringNamespace": "daily_engineering",
"monitoringFirstRunPolicy": "storeOnly",
"keywordInclude": ["engineer"],
"maxJobs": 500
}

The first run stores matching jobs without emitting them. Later runs using the same monitoring store and namespace emit newly discovered matching jobs.

Conservative custom run

{
"companyUrls": ["https://www.linkedin.com/company/google"],
"runProfile": "custom",
"maxJobs": 250,
"maxPagesPerCompany": 20,
"maxRunTimeSeconds": 1200,
"requestTimeoutSeconds": 60,
"maxRequestRetries": 4,
"retryDelaySeconds": 2,
"requestDelayMillis": 2000,
"detailConcurrency": 1,
"failurePolicy": "continue",
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}

Job output

The default dataset contains job records only. It does not mix run summaries into CSV or API exports.

Core fields

FieldDescription
jobIdLinkedIn job ID, or null when it cannot be derived safely.
titlePublic job title.
companyCompany name shown on the listing.
companyIdLinkedIn company identifier used for public job pagination.
companyNameNormalizedClean company name for matching and CRM workflows.
companyLinkedinUrlNormalized input company URL.
locationRaw public LinkedIn location.
city, state, countryBest-effort structured location components.
isRemoteRemote signal inferred from public location and detail metadata.
urlCanonical public LinkedIn job URL.
datePostedPublic posting date when available.
scrapedAtUTC extraction timestamp.
inputUrlCompany URL that produced the record.

Detail fields

FieldDescription
employmentTypePublic employment type when available.
seniorityLevelPublic seniority value when available.
workplaceTypeRemote, Hybrid, or On-site when inferred or published.
applicantsPublic applicant text when exposed.
applyUrlPublic apply link when exposed.
descriptionTextPlain-text description when requested and available.
descriptionHtmlOriginal description HTML fragment when requested and available.
detailStatusnot_requested, loaded, unavailable, or failed.
descriptionStatusnot_requested, loaded, not_available, unavailable, or failed.
detailErrorShort error message when a detail request fails.

Example:

{
"jobId": "4201938821",
"title": "Senior Software Engineer",
"company": "Example Company",
"companyId": "1441",
"companyNameNormalized": "Example Company",
"companyLinkedinUrl": "https://www.linkedin.com/company/example-company",
"location": "San Francisco, CA",
"city": "San Francisco",
"state": "CA",
"country": "United States",
"isRemote": false,
"workplaceType": "Hybrid",
"employmentType": "Full-time",
"seniorityLevel": "Mid-Senior level",
"applicants": "25 applicants",
"applyUrl": "https://www.linkedin.com/jobs/apply/4201938821",
"url": "https://www.linkedin.com/jobs/view/4201938821",
"datePosted": "2026-06-05",
"scrapedAt": "2026-06-06T08:30:00.000Z",
"inputUrl": "https://www.linkedin.com/company/example-company",
"detailStatus": "loaded",
"descriptionStatus": "loaded",
"descriptionText": "About the role...",
"descriptionHtml": "<p>About the role...</p>"
}

Null detail fields are normal when LinkedIn does not publish them.

Run summary and diagnostics

The default key-value store contains:

RecordPurpose
RUN_SUMMARYFinal status, stop reason, totals, timing, resolved non-secret configuration, per-company outcomes, and failures.
RUN_DIAGNOSTICSCompact failure, malformed-card, and filter-reason diagnostics.
MONITORING_INFOMonitoring store and namespace used by the run, or { "enabled": false }.

RUN_SUMMARY.status can be:

  • succeeded: all processed companies completed without an error.
  • partial: at least one company failed, but jobs were emitted.
  • failed: failures occurred and no jobs were emitted.
  • timed_out: the configured whole-run budget was reached and partial results were preserved.

Common company stop reasons include:

  • max_jobs_reached
  • max_pages_reached
  • no_more_jobs
  • no_public_jobs_found
  • repeated_page_detected
  • duplicate_company_skipped
  • max_total_jobs_reached
  • request_budget_reached
  • unparseable_page
  • company_error

Filtering and counting semantics

maxJobs means matching jobs accepted per company, not raw cards scanned.

The Actor processes records in this order:

  1. Parse and normalize the public job card.
  2. Remove duplicates across pages, company aliases, and the entire run.
  3. Skip known monitoring keys when newJobsOnly is enabled.
  4. Apply posting-date, keyword, and raw-location filters.
  5. Fetch detail metadata when requested or required by filters.
  6. Apply remote, workplace, employment, and seniority filters.
  7. Save accepted jobs, unless the first monitoring baseline is configured as storeOnly.

The summary separates scanned, accepted, emitted, filtered, duplicate, malformed-card, and HTTP-attempt counts. requestsPerEmittedJob makes low-yield or unusually expensive runs visible without inspecting every log line.

Scheduling new-job alerts

  1. Run the Actor once with newJobsOnly: true.
  2. Select monitoringFirstRunPolicy: "storeOnly" if the initial backlog should not trigger alerts.
  3. Create an Apify schedule with the same input.
  4. Keep the same monitoringStoreId and monitoringNamespace.
  5. Connect the dataset to a webhook, Make, Zapier, Slack, Google Sheets, a database, or your own API.

Changing filters while reusing a namespace changes what can be considered new. For independent alert logic, create a new namespace.

To intentionally rebuild a baseline, set resetMonitoring: true for one run, then turn it off again.

API and local use

The Actor accepts the same JSON through Apify Console, the Apify API, schedules, tasks, and integrations.

For local development, create:

storage/key_value_stores/default/INPUT.json

Example local input:

{
"companyUrls": ["https://www.linkedin.com/company/google"],
"runProfile": "fast",
"maxJobs": 10,
"maxPagesPerCompany": 1,
"maxRunTimeSeconds": 120,
"proxyConfiguration": {
"useApifyProxy": false
}
}

Then run:

$apify run

Local storage remains on your machine and is not uploaded to Apify Console.

Cost and performance

The main cost drivers are:

  • Number of companies.
  • Number of listing pages.
  • Number of accepted candidate jobs.
  • Whether detail requests are required.
  • Proxy traffic.
  • Retry volume and total runtime.

For lower cost:

  • Start with the Fast profile.
  • Keep scrapeDescription disabled.
  • Apply date, keyword, and location filters before detail enrichment.
  • Set a realistic maxJobs.
  • Keep maxTotalJobs and maxRequestsPerRun bounded.
  • Keep maxPagesPerCompany bounded.
  • Use monitoring so recurring runs skip known matching jobs before detail requests.

For higher data completeness:

  • Use the Enriched profile.
  • Keep includeJobsWithUnknownMetadata enabled unless strict filtering is required.
  • Use a Residential proxy group.
  • Allow a larger whole-run budget.

Troubleshooting

The Actor says the URL is invalid

Use a full public company URL:

https://www.linkedin.com/company/google

Individual job URLs, personal profiles, /jobs/search pages, and non-LinkedIn URLs are not company targets.

A company fails before jobs are collected

The company may be unavailable, renamed, geographically restricted, or served behind an authentication wall. Check RUN_SUMMARY.failures and RUN_DIAGNOSTICS.

With failurePolicy: "continue", other companies are still processed.

The dataset is empty

Check:

  • RUN_SUMMARY.companies[].stoppedReason
  • jobsFilteredOut
  • filteredBy
  • duplicatesSkipped
  • monitoringBaselineStoredOnly
  • failureCount

An empty dataset can be expected when the first monitoring run uses storeOnly, all matches are already known, filters reject all jobs, or LinkedIn exposes no public jobs.

Some detail fields are null

LinkedIn does not expose every field for every job. Inspect detailStatus and descriptionStatus. A null field with detailStatus: "loaded" usually means the public page omitted it.

Monitoring emits old jobs again

Confirm that scheduled runs use the same persistent monitoring store and namespace. A new store, namespace, or reset creates a new baseline.

The run stops with time_budget_reached

Already emitted jobs remain in the dataset. Increase maxRunTimeSeconds, lower maxJobs, reduce the number of companies, disable detail enrichment, or reduce retries.

The run stops at a request or result budget

request_budget_reached protects against retry, pagination, or enrichment amplification. max_total_jobs_reached protects against unexpectedly large datasets across many companies. Already emitted jobs remain available. Increase the relevant limit only after checking requestAttempts, requestsPerEmittedJob, filters, monitoring settings, and the number of companies.

Requests are blocked or unstable

Use Apify Residential Proxy, lower detail concurrency, increase request pacing, and avoid aggressive retry settings. Public LinkedIn page behavior can vary by region and over time.

Data quality and limitations

  • The Actor only returns jobs visible through LinkedIn's public company and guest job surfaces.
  • Public availability, selectors, fields, and pagination behavior can change without notice.
  • Parsed location fields are best-effort. Always retain the raw location.
  • Remote classification is based on public text and may not capture every employer-specific arrangement.
  • Applicant counts and apply links are not always exposed.
  • Job IDs are preferred for deduplication; the canonical job URL is used when an ID is unavailable.
  • Deleted or expired postings may disappear between runs.
  • The Actor cannot guarantee that LinkedIn publishes every open role for a company.

Responsible use

Use the Actor only for lawful purposes and public data you are permitted to process. Respect applicable privacy, employment, anti-discrimination, database, and contract rules. Avoid collecting or retaining personal information from job descriptions unless your workflow has a legitimate need and appropriate safeguards.

This Actor is not affiliated with, endorsed by, or sponsored by LinkedIn Corporation or Microsoft. LinkedIn is a trademark of its respective owner.

Support

When reporting an issue, include:

  • Apify run ID.
  • A minimal input that reproduces the problem.
  • Affected company URL.
  • Relevant RUN_SUMMARY and RUN_DIAGNOSTICS fields.
  • Expected and actual behavior.

Do not include Apify tokens, proxy passwords, cookies, or other credentials.