# LinkedIn Company Scraper - Profile, Size, Posts (`webdata_labs/linkedin-company-scraper`) Actor

\[💵 $2.9 / 1K · no start fee] Full LinkedIn company profile from a slug or URL, no login: industry, size band, headcount, followers, founded year, specialties, website, every office, the numeric company id and recent posts with engagement. You only pay for companies that parse.

- **URL**: https://apify.com/webdata\_labs/linkedin-company-scraper.md
- **Developed by:** [WebData Labs](https://apify.com/webdata_labs) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 companies

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## LinkedIn Company Scraper

**Turn a list of LinkedIn company slugs into a clean firmographic table: industry, size, headcount, followers, founded year, specialties, website, every office, the numeric company id and recent posts with engagement.**

You have a list of companies and a spreadsheet with three useful columns. Enriching it by hand means opening every LinkedIn page, squinting at the About block, copying the industry, the size band and the website, and pasting them into the right row. Do that for 400 accounts and you have burned two days on transcription. This Actor reads the same public company pages and hands the whole About block back as flat rows, with the fields LinkedIn shows but nobody bothers to copy: the numeric company id, every office address, and whether the page has posted anything this year.

### ✅ What you get / ❌ what this isn't

| ✅ What you get | ❌ What this isn't |
|---|---|
| **35 fields per company**, including the numeric LinkedIn company id | Not the 15-field name-industry-size stub most company scrapers stop at |
| **The whole office list**, one entry per location with street, city and country | Not just the single HQ line printed at the top of the About block |
| **Post activity**: last post date, recent post bodies, reaction and comment counts | Not a static profile snapshot that treats a dead page and a daily poster the same |
| **Affiliated and similar pages**, as slugs you can feed straight back in | Not a dead end that leaves you hand-hunting the rest of the competitive set |
| **A row for every input**, including dead slugs, with the reason attached | Not a silently short dataset where you have to diff the output against your input |
| **You are only charged for companies that parsed** | Not per-row billing where 404s and auth walls cost the same as real data |
| **No login, no cookies, no LinkedIn account at risk** | Not a session-cookie scraper that can get an account restricted |

### 🔎 Why use this Actor

- **The numeric company id.** Every row carries LinkedIn's internal organization id (Stripe is `2135371`). It is the key LinkedIn Ads, Sales Navigator and the partner APIs join on, it is not printed anywhere on the page, and unlike the slug it survives a company renaming its URL.
- **Size band and headcount, kept apart.** `companySize` is the band the company selected ("5,001-10,000 employees"), parsed into `employeeCountMin` and `employeeCountMax` so you can filter numerically. `employeeCount` is the separate, much larger number LinkedIn derives from profiles listing that employer. Mixing the two is the single most common error in company data; here they are three distinct fields.
- **Post activity as a qualification signal.** `lastPostAt`, `postsSampled` and `avgReactionsPerPost` tell you whether a page is alive before you spend a rep's time on it. A company that last posted in 2023 is a different lead from one that posted yesterday to 4,000 reactions.
- **Every office, not just the HQ.** `locations` holds one entry per address LinkedIn lists, so territory assignment and "do they have a European entity" questions get answered from the same row.
- **List expansion built in.** `affiliatedPages` gives you subsidiaries, regional and brand pages; `similarPages` gives you LinkedIn's own set of comparable companies. Both come back as slugs, so a run over 20 seed accounts feeds the next run over their whole neighbourhood.
- **Paste whatever you have.** Full URLs, country URLs (`au.linkedin.com/...`), showcase pages, `/about/` URLs with tracking parameters, or bare slugs. The same company arriving in three shapes is deduplicated and billed once.
- **Dead inputs are answered, not dropped.** A renamed slug returns a `not_found` row explaining that LinkedIn merges and renames company pages constantly. A personal profile URL returns a row saying so. Neither is charged.

### 👥 Who it's for

Sales, revops, recruiting and market-research teams who already have a list of target companies and need it enriched into something a CRM or an ICP filter can act on.

- Enrich an account list with industry, size band, headcount and HQ country before territory planning.
- Score inbound signups by company size and industry without asking the user a single extra question.
- Build a competitor set from three seed companies by following `similarPages` and `affiliatedPages`.
- Qualify a partner or vendor list by page activity, so nobody pitches a company that went quiet two years ago.
- Match a LinkedIn Ads or Sales Navigator export back to your own records on the numeric company id.
- Pull every office of a multinational for territory or compliance mapping.

### Example tasks

- [Enrich a list of LinkedIn companies](https://apify.com/webdata_labs/linkedin-company-scraper/examples/linkedin-company-data-enrichment) - the generic run: a mixed account list in, firmographics out.
- [Scrape SaaS company profiles from LinkedIn](https://apify.com/webdata_labs/linkedin-company-scraper/examples/linkedin-saas-company-profiles) - software vendors, with specialties and recent posts.
- [Scrape e-commerce brand profiles from LinkedIn](https://apify.com/webdata_labs/linkedin-company-scraper/examples/linkedin-ecommerce-brand-profiles) - retail brands, framed around the address block and website.
- [Scrape recruiting and staffing agency profiles](https://apify.com/webdata_labs/linkedin-company-scraper/examples/linkedin-recruiting-agency-profiles) - agencies, with posting activity attached.
- [Check which LinkedIn company pages are still active](https://apify.com/webdata_labs/linkedin-company-scraper/examples/linkedin-company-page-activity-check) - the qualification run: last post, engagement, followers.
- [Expand a seed list into a full competitor set](https://apify.com/webdata_labs/linkedin-company-scraper/examples/linkedin-competitor-list-expansion) - three seeds in, LinkedIn's own similar and affiliated pages out.

### ⚙️ How to enrich a list of companies

1. Paste your LinkedIn company URLs or slugs into **Company URLs or slugs**. One per line, in any of the accepted shapes; a column pasted straight out of a spreadsheet works.
2. Set **Max companies** to bound the run. It defaults to 100 so a first run is cheap; set `0` for unlimited when you are ready to run the whole list.
3. Leave **Include recent posts** and **Include affiliated and similar pages** on unless you want a narrower row. They do not change the price.
4. Pick a **Language** if you want the industry and size labels in something other than English.
5. Click **Start**. Results stream into the dataset as each page is parsed, so you can watch the first rows before the run finishes, and export to CSV, Excel, JSON or straight into an integration from the **Storage** tab.

#### Expanding a seed list into a full market map

Run 10 companies you know. Open the dataset, take the `similarPages` and `affiliatedPages` slugs from those rows, and paste them into a second run. Two rounds of this typically turns a handful of accounts into a few hundred comparable companies, all with the same fields, and LinkedIn's own similarity model does the selection for you.

### 📥 Input

```json
{
  "companyUrls": [
    "https://www.linkedin.com/company/stripe",
    "shopify",
    "https://au.linkedin.com/company/atlassian",
    "https://www.linkedin.com/showcase/microsoft-azure"
  ],
  "maxCompanies": 100,
  "includePosts": true,
  "maxPostsPerCompany": 10,
  "includeRelatedCompanies": true,
  "language": "en"
}
```

- `companyUrls` - the companies to scrape. Full URLs, country URLs, showcase pages, `/about/` URLs with tracking parameters, or bare slugs. Duplicates across shapes are merged. Numeric company ids do **not** work as input, because LinkedIn only serves those behind the login wall; use the slug from the page URL.
- `maxCompanies` - cap on how many companies from the list get scraped. Default `100`, `0` means unlimited. There is no hard ceiling.
- `includePosts` - attach recent public posts with text, timestamps and engagement counts, plus `lastPostAt`. Default `true`.
- `maxPostsPerCompany` - how many posts to attach per company. Default `10`, which is roughly what a logged-out page exposes.
- `includeRelatedCompanies` - attach `affiliatedPages` and `similarPages`. Default `true`.
- `language` - language for the industry name, size band and organization type. The company's own name and description always come back as the company wrote them. Default `en`.

Proxying, pacing and retries are handled internally and there is nothing to configure.

### 📤 Output

| name | industry | companySize | employeeCount | followerCount | headquarters | website | companyId | lastPostAt |
|---|---|---|---|---|---|---|---|---|
| Stripe | Technology, Information and Internet | 5,001-10,000 employees | 17141 | 1631601 | South San Francisco, California | https://stripe.com | 2135371 | 2026-08-07T16:15:36.101Z |
| Atlassian | Software Development | 10,001+ employees | 16939 | 2608860 | Sydney, NSW | https://atlassian.com | 22688 | 2026-08-13T22:22:44.517Z |
| Shopify | Software Development | 10,001+ employees | 29696 | 1102266 | Ottawa, ON | https://www.shopify.com | 784652 | 2026-08-13T14:14:16.600Z |

Every row also carries `slug`, `linkedinUrl` and `sourceInput` (the exact string you pasted, so joins back to your list never guess); `tagline` and `description` as the company wrote them; `foundedYear`, `companyType` and `specialties` as an array; `employeeCountMin` / `employeeCountMax` parsed out of the size band; `logoUrl`; the address split into `street`, `city`, `state`, `postalCode` and `country`, plus `locations` holding every office LinkedIn lists; `postsSampled`, `firstSampledPostAt`, `avgReactionsPerPost` and `recentPosts` (each with `postUrl`, `postedAt`, `text`, `isRepost`, `reactions` and `comments`); `affiliatedPages` and `similarPages` as `{name, slug, industry, linkedinUrl}` objects; and `status` / `statusMessage`, which say `ok` on a real company and explain themselves on the rows that are not.

### 💵 How much does it cost?

**$2.90 per 1,000 companies** on the free tier, dropping to **$0.70 per 1,000** on higher Apify plans, and there is **no Actor start fee**. You are charged per company that actually parsed: a dead slug, a personal-profile URL or a page LinkedIn refused to serve still lands in your dataset as an explained row, but it costs nothing. Turning the posts or related-pages blocks off does not change the price, because a company is one charge either way. A typical 500-account enrichment run costs about $1.45 and finishes in a couple of minutes.

### 🔁 Run it on the Apify platform

Schedule the Actor to re-run your account list monthly and watch headcount, size band and follower count drift over time; that delta is a decent growth signal. Every run is reachable from the API, and the dataset exports to CSV, Excel, JSON, XML or RSS. Webhooks fire on finish, and the Make, Zapier and n8n integrations push rows straight into HubSpot, Salesforce, Airtable or a Google Sheet without any glue code.

### ⚠️ Limits and caveats

- **Public company pages only.** Everything here comes from the page LinkedIn serves to logged-out visitors. Tabs behind the login wall (`/people/`, `/jobs/`, `/insights/`) are not read, and no LinkedIn account is used, so nothing here can get an account restricted.
- **No named employees.** This Actor returns organization data. It does not collect employee names, titles or personal profiles.
- **`employeeCount` is LinkedIn's associated-member count, not a payroll number.** It counts profiles listing the company as their employer, so it runs well above the self-reported `companySize` band for well-known employers and it includes alumni-style stragglers. Treat the band as the company's own claim and the count as LinkedIn's, and expect them to disagree.
- **Some About rows are simply empty.** Founding year, specialties and the address block are optional on LinkedIn, and plenty of large companies leave them blank. Those fields come back `null` rather than guessed.
- **About 10 posts, not the full archive.** The logged-out page renders roughly the last ten updates, so `lastPostAt` and `avgReactionsPerPost` are exact while `postsSampled` is a window, not a lifetime count.
- **Showcase pages are thinner.** `/showcase/` pages parse fine but often carry no organization type, founding year or address, because LinkedIn does not ask for them.
- **University and school pages are not covered.** LinkedIn serves `/school/` pages to logged-in visitors only, Harvard included, so those inputs come back as an explained row rather than data. A handful of company slugs quietly redirect onto a school page; those are flagged `school_page` and are not charged.
- **Numeric company ids cannot be used as input.** LinkedIn resolves `/company/<number>` only for logged-in visitors. The id comes back in the output; it does not work going in.
- **Follower counts are rounded by LinkedIn at the top of the page** but exact in the metadata this Actor reads, so expect small disagreements with what you see in a browser.

### 🧩 Related Actors

- **Website Contact Extractor** - feed the `website` column from these rows in to pull emails and phone numbers off each company site.
- **Website Tech Stack Detector** - same `website` column, returns the technologies each company runs, for technographic targeting.
- **Company Career Page Jobs API** - turns the same company list into their live open roles, which is the strongest hiring-intent signal there is.
- **LinkedIn Ads Library Scraper** - shows which of these companies are actively running paid campaigns.
- **Lead List Deduplicator** - clean and merge the enriched list against your existing CRM export before import.
- **Google Maps Business Scraper API** - matches these companies to their physical locations, ratings and phone numbers.

### ❓ FAQ

**Do I need a LinkedIn account or cookies?**
No. The Actor reads the public company page LinkedIn serves to logged-out visitors. There is nothing to log into and no session to supply.

**Am I charged for slugs that do not exist?**
No. Dead slugs, personal-profile URLs and pages LinkedIn refused to serve are written to the dataset as explained rows with a `status` other than `ok`, and those rows carry no charge.

**Can I pass a company name or a website domain instead of a slug?**
Not yet. LinkedIn's company search is behind the login wall, so the Actor needs the slug or the page URL. The slug is the last path segment of the company page URL.

**Why is `employeeCount` so much bigger than the size band?**
They measure different things. The band is what the company selected on its own page; the count is how many LinkedIn profiles list that company as their employer. Both are in every row so you can pick the one your model wants.

**Which countries and languages does it cover?**
Any company page on any LinkedIn country domain. The `language` input controls the labels LinkedIn renders (industry, size band, organization type); company names and descriptions always come back as written.

**How do I get a fresh snapshot every month?**
Save your input as a Task and put it on a schedule. Each run writes a new dataset, so comparing headcount, followers and `lastPostAt` across runs gives you a growth and activity trend per account.

### 🛠️ Support

Something wrong or missing? Open an issue on the Actor's Issues tab with the run URL, the input you used and what you expected. Bug reports with a run URL get fixed fastest.

### ⭐ Rate this Actor

If this saved you an afternoon of copy-pasting, please leave a review on the **Reviews** tab. Reviews are the main trust signal buyers use on the Store, and they are also how we decide what to build and fix next. If something is broken, please open an issue first so we can fix it, rather than rating it low with no way to reach you.

# Actor input Schema

## `companyUrls` (type: `array`):

LinkedIn company pages to scrape. Accepts the full URL (https://www.linkedin.com/company/stripe), a country URL (https://au.linkedin.com/company/atlassian), a showcase page (/showcase/microsoft-azure) or just the slug (stripe). Numeric company ids do not work - LinkedIn hides them behind the login wall - so use the slug from the page URL.

## `maxCompanies` (type: `integer`):

Cap on how many companies from the list get scraped. Keeps an accidental paste of 5,000 rows from becoming a surprise bill. Set 0 for unlimited - there is no hard ceiling.

## `includePosts` (type: `boolean`):

Attach the company's recent public posts with their text, timestamps and reaction/comment counts, plus a lastPostAt field. This is the signal that separates an active company page from an abandoned shell, which matters when you are qualifying a list.

## `maxPostsPerCompany` (type: `integer`):

How many recent posts to attach per company. The logged-out page exposes about 10, so anything above that just returns what LinkedIn shows.

## `includeRelatedCompanies` (type: `boolean`):

Attach the company's affiliated pages (subsidiaries, regional and brand pages) and the similar companies LinkedIn itself lists. Feed these slugs back into a second run to expand a seed list into a whole competitive set.

## `language` (type: `string`):

Language for the industry name, company-size band and organization type. The company's own description and name always come back as the company wrote them.

## Actor input object example

```json
{
  "companyUrls": [
    "https://www.linkedin.com/company/stripe",
    "shopify",
    "https://au.linkedin.com/company/atlassian"
  ],
  "maxCompanies": 2,
  "includePosts": true,
  "maxPostsPerCompany": 5,
  "includeRelatedCompanies": true,
  "language": "en"
}
```

# Actor output Schema

## `companies` (type: `string`):

No description

## `activity` (type: `string`):

No description

## `contact` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companyUrls": [
        "stripe",
        "apify"
    ],
    "maxCompanies": 2,
    "includePosts": true,
    "maxPostsPerCompany": 5,
    "includeRelatedCompanies": true,
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("webdata_labs/linkedin-company-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "companyUrls": [
        "stripe",
        "apify",
    ],
    "maxCompanies": 2,
    "includePosts": True,
    "maxPostsPerCompany": 5,
    "includeRelatedCompanies": True,
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("webdata_labs/linkedin-company-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companyUrls": [
    "stripe",
    "apify"
  ],
  "maxCompanies": 2,
  "includePosts": true,
  "maxPostsPerCompany": 5,
  "includeRelatedCompanies": true,
  "language": "en"
}' |
apify call webdata_labs/linkedin-company-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,webdata_labs/linkedin-company-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/onjHgErhIuimYl1Sb/builds/VXmDaduO0cSfaw2wl/openapi.json
