LinkedIn Company Scraper – Posts & Followers
Pricing
$1.00 / 1,000 company reads
LinkedIn Company Scraper – Posts & Followers
Scrape any public LinkedIn company page: follower count, tagline, full description, logo, website, industry, size, headquarters, address and founding year, plus its latest posts with text, publish time, reactions and comments. No login, no API key — one request a company. Unofficial.
Pricing
$1.00 / 1,000 company reads
Rating
0.0
(0)
Developer
Simple Actors
Maintained by CommunityActor stats
0
Bookmarked
4
Total users
3
Monthly active users
21 hours ago
Last modified
Categories
Share
Scrape any public LinkedIn company page: its follower count, tagline, full description, logo, website, industry, size, headquarters and founding year, plus its latest posts with full text, exact publish time, reactions and comments. Built for B2B lead research, competitor and brand monitoring, CRM enrichment and social listening across many companies at once.
One request a company. Everything comes out of the single page LinkedIn
serves at /company/<slug> — there is no second call, no cursor and no API.
A company reads in a few seconds.
$1 per 1,000 companies read — Apify platform usage and proxy included, nothing else to pay. The charge is per company and does not depend on how many posts come back, so a full read and a check that finds one new post cost the same. A company that could not be read is never charged.
No login, no cookies, no API key, no account of yours involved. It reads what LinkedIn already renders for logged-out visitors, so there is no session to keep alive and nothing of yours to get restricted.
Unofficial. Not affiliated with, endorsed by, or sponsored by LinkedIn or Microsoft.
Read this before you start: company pages only. Personal profiles (
linkedin.com/in/…) are served behind a login and cannot be read — they come back as a row saying so. And a company page renders roughly 9 to 11 posts to a logged-out reader, with no way to page further. This is built to check many companies often, not to pull one company's archive.
Features
- The company record — name, follower count, tagline, description and logo. The description is the company's full About-us text, not the shortened version LinkedIn puts in the page's preview tag.
- The whole About-us panel — website, industry, company size, headquarters, postal address, organisation type, founding year and specialities. The website comes out unwrapped, as the company's own address rather than the LinkedIn redirect the page links to.
- The latest posts — up to 12, newest first, each with its text, permalink, publish time, reaction count and comment count.
- Exact publish times on every post, including the ones LinkedIn does not date in its structured data — the time is recovered from the post's own activity id.
- Untruncated text where LinkedIn provides it, flagged per post with
textIsCompleteso a shortened card can never pass for a full one. - Reposts flagged —
isRepostmarks a post the company shared rather than wrote, whose reactions belong to the original. - Stable post ids — deduplicate across scheduled runs on
id. - Every URL form works — full URLs, locale hosts (
uk.linkedin.com), sub-pages (/about/),/school/pages, or a bare slug pasted from a spreadsheet. - Two output shapes — one row per post, or one row per company with its posts nested. Same price.
- Incremental polling —
onlyPostsNewerThantakes3 days,12 hoursor an ISO date, and refuses rather than misleads when the window reaches past what one page shows. - Datacenter proxy is enough, which is what keeps it cheap.
- Runs stay green. Every company that cannot be read — one that does not exist, a personal-profile URL, a window too wide, or LinkedIn refusing on the day — is a row, not a failed run.
Input
{"startUrls": [{ "url": "https://www.linkedin.com/company/dishoom" }], // company URLs"companies": ["vercel", "stripe"], // or bare slugs — both lists are read as one"outputFormat": "posts", // "posts" = row per post, "company" = row per company"maxPosts": 12, // latest posts per company (12 is the ceiling)"onlyPostsNewerThan": "7 days", // optional window: "12 hours", "3 days", "2026-08-01""proxy": { "useApifyProxy": true }}
The shortest useful input is a list of slugs:
{ "companies": ["dishoom", "vercel", "stripe"] }
| Field | Type | Default | What it does |
|---|---|---|---|
startUrls | array | — | Company pages as URLs. Locale hosts, sub-pages and /school/ all work. |
companies | array | — | The slug on its own — the part after /company/ in the address bar. Read together with startUrls. |
outputFormat | string | posts | posts gives one row per post; company gives one row per company with its posts nested. |
maxPosts | integer | 12 | Latest posts per company. 12 is the ceiling — one page is all LinkedIn serves. |
onlyPostsNewerThan | string | — | Keep only posts after a window or ISO date. |
proxy | object | datacenter | Datacenter is what this is built and measured on. |
The slug is often not the brand name. It is whatever appears after
/company/ in the address bar — check there rather than guessing, or you will
get a not_found row.
Output
One row per post by default, with the company record repeated on each:
{"type": "post","id": "7495121826755391488","url": "https://www.linkedin.com/posts/dishoom_everything-we-ate-and-drank-at-dishoom-leeds-activity-7495121826755391488-6YOH","text": "\"Taking over the old Flannels site on Vicar Lane, Dishoom Leeds is nothing short of beautiful…\"","textIsComplete": true,"postedAt": "2026-08-17T14:18:16.104Z","postedAtIsApproximate": false,"reactions": 61,"comments": 3,"isRepost": false,"postAuthorName": "Dishoom","postAuthorUrl": "https://uk.linkedin.com/company/dishoom","companyUrl": "https://www.linkedin.com/company/dishoom","companyName": "Dishoom","companySlug": "dishoom","followers": 34996,"tagline": "From Bombay with love","description": "Dishoom is proud to be recognised as one of the best places to work in hospitality…","logo": "https://media.licdn.com/dms/image/…/company-logo_200_200/…","website": "http://careers.dishoom.com/","industry": "Restaurants","companySize": "1,001-5,000 employees","employeesOnLinkedIn": 996,"headquarters": "London","organizationType": "Privately Held","foundedYear": 2010,"specialties": [],"address": {"street": "141-143 Shoreditch High Street","city": "London","region": null,"postalCode": "E1 6JE","country": "GB","raw": "141-143 Shoreditch High Street, London, E1 6JE, GB"},"scrapedAt": "2026-08-30T09:00:00.000Z"}
Set outputFormat to company and each company is a single row instead, with
its posts under posts — the shape to pick when you are looking at companies
rather than collecting posts.
| Field | What it is |
|---|---|
id | LinkedIn's activity id. Stable across runs — deduplicate on it. |
url | Permanent link to the post. |
text | The post's text. |
textIsComplete | true when the text is untruncated. false means it is the card's shortened commentary — LinkedIn publishes the full text for only some posts. |
postedAt | When it was published, ISO 8601 UTC. Never null. |
postedAtIsApproximate | true when the time was decoded from the activity id rather than stated by LinkedIn. Accurate to a fraction of a second either way. |
reactions, comments | Counts as LinkedIn displays them. null means none was shown, never zero. |
isRepost | true when the company shared someone else's post. Its engagement belongs to the original — do not credit it to this company. |
followers | The company's follower count, taken from the page's own metadata rather than from the related-companies sidebar, which carries other companies' counts. |
description | The company's About-us text in full, however long it runs. |
tagline | The one-line slogan under the company name. |
website | The company's own site, with LinkedIn's redirect stripped off — ready to feed to anything that takes a URL. |
industry | The industry the company files itself under, in LinkedIn's words. |
companySize | The headcount band the company declares, e.g. 11-50 employees. |
employeesOnLinkedIn | How many employee profiles LinkedIn associates with the company. A different fact from companySize — Vercel declares 501-1,000 and has 1,013 profiles. |
headquarters | The head-office city as LinkedIn shows it. |
address | Street, city, region, postal code, country, and raw — the whole thing on one line. More precise than headquarters. null when the company publishes none. |
organizationType | Privately Held, Public Company, Partnership, Nonprofit, and so on. |
foundedYear | The year the company says it was founded. |
specialties | The specialities the company lists, one per entry. [] when it lists none. |
scrapedAt | When the run read the page. |
How to use
From Apify Console
- Open the Actor and click Try for free / Start.
- Paste company URLs into LinkedIn company URLs, or a column of bare slugs into Company slugs — both lists are read together.
- Choose the row shape in Row shape: one row per post for collecting posts, one row per company for watching companies.
- To poll for what is new, set Only posts newer than to a window shorter than the gap between your runs, and schedule the run.
- Click Start, then open the Dataset tab and export as JSON, CSV or Excel.
Batch your companies — one run with fifty slugs is far cheaper per company than fifty runs of one, because each run pays its own startup.
From the API
curl -s "https://api.apify.com/v2/acts/simple.actors~linkedin-company-posts/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"companies": ["dishoom", "vercel", "stripe"]}'
Monitoring a set of companies, with the JavaScript client:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('simple.actors/linkedin-company-posts').call({companies: ['dishoom', 'vercel', 'stripe'],onlyPostsNewerThan: '24 hours',});const { items } = await client.dataset(run.defaultDatasetId).listItems();for (const row of items) {if (row.error) { console.warn(row.companySlug, row.error); continue; }if (row.isRepost) continue; // engagement belongs to the originalconsole.log(row.companyName, row.postedAt, row.reactions, row.text?.slice(0, 60));}
Use cases
- B2B lead research — pull follower count, industry, company size, founding year and headquarters across a list of target companies to size and qualify them.
- Competitor content monitoring — see what rival companies posted, when, and how it performed, on a schedule.
- Brand and campaign tracking — watch reactions and comments on a company's own posts over time.
- CRM enrichment — attach a follower count, description, industry, size and postal address to accounts you already hold, matched by slug.
- Website discovery — the
websitefield turns a list of LinkedIn slugs into a list of company domains, which is what a contact or tech-stack lookup needs as its input. - Social listening across platforms — combine with the Instagram, TikTok, X, YouTube and Facebook readers for one view of a company's presence.
- Employer-brand research — a company's own posts are what it chooses to say publicly; collect them across an industry.
Usage notes
Simple, transparent pay-per-result pricing — no subscriptions.
What it costs
$0.0010 per company read — $1 per 1,000 companies. One charge per company, whatever the run finds. There is no per-run fee and no per-post fee: reading a company costs the same whether ten posts come back or one, so charging for them would bill you for something that is not what costs.
Two things follow from that:
- Batch your companies. Fifty slugs in one run is much cheaper per company than fifty runs of one, because each run pays for its own startup.
- Take all the posts. Asking for fewer saves you nothing.
A company that could not be read is never charged — a slug that does not exist, a personal-profile URL, a window too wide, or a page that could not be reached. So a list carrying dead entries costs only for the live ones.
What an empty result means. A company that was read but has posted nothing
in your window still comes back as a company row, so an empty-looking result
can never be confused with a company that was not read. A company that could
not be read is its own row carrying error and errorDescription.
The rows are the failure channel, not the run status. The run succeeds even
when some — or all — of its companies could not be read, and the status message
counts them. No unreadable company fails a run: not one of them, and not all of
them at once. If you schedule this, treat any row with an error field as the
failure signal — a run status of SUCCEEDED does not by itself mean every company
came back.
error | what happened | Run status |
|---|---|---|
not_found | LinkedIn has no company page at that slug | Succeeds |
bad_input | The entry was never a company page — a personal profile, or not a LinkedIn URL at all | Succeeds |
window_too_wide | The window reaches further back than one page shows | Succeeds |
read_failed | LinkedIn could not be reached after four attempts | Succeeds |
onlyPostsNewerThan refuses rather than misleads. A run sees one page of
posts and no further back. If your window reaches past them, posts inside it
were never fetched — and returning what was found would read as "this is
everything since then". So that company gets a window_too_wide row instead,
naming how far back it could actually see. A company that posts daily will
answer that for most windows; use a shorter one, or run more often.
LinkedIn refuses some requests outright with its own HTTP 999 status. That refusal is random per request rather than tied to a company, so it is retried on a fresh address up to four times — which cleared every refusal measured.
Limits
- Company pages only. Personal profiles need a login and come back as a
bad_inputrow explaining that. - Roughly 9 to 11 posts per company, 12 at most. That is what LinkedIn renders to a logged-out reader; there is no cursor to ask for more. Run on a schedule to follow a company over time.
- No comment text. The page carries comment counts, not the comments.
- Reactions are not broken down by type. LinkedIn shows a single total to a logged-out reader.
- Reposts carry the original's engagement. They are flagged
isRepostso you can exclude them.
FAQ
Is scraping LinkedIn legal? This Actor reads only what LinkedIn already renders to a logged-out visitor, without logging in or using cookies. LinkedIn's User Agreement restricts automated collection, so check the platform's ToS and your own obligations — particularly around personal data — before using it, and run it at a volume and rate you are comfortable defending.
Do I need a LinkedIn login, cookies or an API key? No. There is no session, token or account of yours involved.
Can it read personal profiles (/in/…)?
No. LinkedIn serves those behind an authwall to a logged-out reader, so there is
nothing to return. Those entries come back as a bad_input row saying so rather
than as a silent failure.
Can I get a company's full post history? No. One page renders roughly 9 to 11 posts and offers no way to page further without a login. This Actor is built to check many companies often; for one company's archive it is the wrong tool.
Why did I get not_found for a company I can see on LinkedIn?
Almost always the slug. It is the part after /company/ in the address bar and
is frequently not the brand name — check there rather than guessing.
Why is reactions null on some posts?
Because LinkedIn showed no count for that post. Null means "none was shown",
never zero, so a count of 0 and an absent count stay distinguishable.
What is postedAtIsApproximate?
LinkedIn states an exact timestamp for only some posts. For the rest the time is
decoded from the post's own activity id, which encodes its publish moment —
measured within a fraction of a second of LinkedIn's own figure. The flag tells
you which you got; both are reliable enough to sort and filter on.
Why did my run succeed when a company was not read?
By design. Every company that cannot be read comes back as a row with an error
field — whether that is an answer about the entry (missing, a personal profile,
a window too wide) or LinkedIn refusing the read on the day — and none of them
turns the run red. Treat those rows as the failure signal rather than the run
status, and read the run's status message for the counts.
Note
This Actor is not affiliated with, endorsed by, or sponsored by LinkedIn or Microsoft. It reads publicly visible company pages without logging in, and cannot reach personal profiles, private pages, connections or anything else behind a login.