LinkedIn Company Scraper & Change Monitor (No Login)
Pricing
from $1.20 / 1,000 companies
LinkedIn Company Scraper & Change Monitor (No Login)
Scrape public LinkedIn company pages: one row per company with name, About, industry, employee band, website, followers and founded year when shown. Use it to watch accounts. Only changes returns only changed companies, with old and new values. No employees or posts. Not affiliated with LinkedIn.
Pricing
from $1.20 / 1,000 companies
Rating
0.0
(0)
Developer
Kizuki
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 hours ago
Last modified
Categories
Security
Limited permissionsShare
LinkedIn Company Scraper & Change Monitor reads public LinkedIn company overviews as any visitor sees them and returns one clean row per company — name, About summary, industry, organisation type, employee band, headquarters, founded year, website, follower count and specialties — as JSON or CSV. With onlyChanges it becomes a monitor: a scheduled run returns only the companies whose fields changed, with the old and the new value of each field — follower count, employee band, summary, industry, headquarters, founded year, website, type and specialties. Under onlyChanges, a company with nothing new produces no row and no charge.
It needs no login, no account and no cookie, runs no browser and executes no JavaScript on the page. Pages it could not read come back as a row with a fixed reason and are not charged, so a wall or a timeout never looks like "no change".
This Actor is an independent tool. It is not affiliated with, endorsed by or sponsored by LinkedIn or Microsoft. Try it with an empty input: it reads the sample company apify and returns its overview.
Use cases
- Competitor watch. Follow a list of companies and get a row only when followers, headcount band, description or industry move.
- Account research. One row per company with industry, size, headquarters, website and specialties, ready for a CRM or a sheet.
- Market mapping. Build a table of companies in one industry and compare employee bands and specialties.
- Sales triggers. Use the follower jump or the employee-band change as the trigger for an alert, not a full re-read of every company.
- Agent research. Let an assistant pull a company's public profile, and only what changed since its last run.
What data can you get?
| Field | Description |
|---|---|
id, type, source | Row ID (a hash of the slug), company, and the source label |
status | ok for successfully read companies, or failed for uncharged status rows |
slug, url | The company slug and the page that was read (https://www.linkedin.com/company/<slug>/) |
name | Company name as on the page |
description | The About us summary, up to 5,000 characters, as the company wrote it |
industry | The industry LinkedIn lists |
companyType | Organization type as shown (Public Company, Privately Held, …) or null |
companySize, employeesMin, employeesMax | The employee band as shown (10,001+ employees) and its numeric bounds (max is null for an open band) |
headquarters | Headquarters as shown (Mountain View, CA) |
foundedYear | The year the page says the company was founded, or null (many pages do not show it) |
website | The company's own website, unwrapped from LinkedIn's redirect link |
followers | Followers on LinkedIn at the time of the run |
specialties | The specialties the page lists (up to 30) |
capturedAt | When the run read the page |
changes | With onlyChanges: {baseline, previousCapturedAt, changedFields, diffs: [{field, from, to}]}, otherwise null |
errorCode, errorMessage | For a status row: authwall, blocked, not_found, timeout or unexpected, with a fixed sentence; null for a company row |
Every row has every field; a value the page does not show is null. Employee lists and personal profiles are not part of this Actor.
A company whose page LinkedIn has moved is read at its new address (mistral-ai → mistralai) and its row keeps the slug you asked for. When the new address belongs to a different company, the row is not_found with an explanatory message: that slug no longer names a company, and reading the other company's page would put its data under your slug.
How to use LinkedIn Company Scraper
- Put company URLs or slugs into Companies (
companies:apify,https://www.linkedin.com/company/google/). Up to 100. - For a one-off overview, leave Only changes since the previous run (
onlyChanges) off: every named company is returned in full. - For monitoring, turn it on, set
maxItemsto bound how many companies one run reads, and schedule the Actor (hourly, daily or weekly). Each run then returns only what changed. - Send the rows to your sheet, warehouse, alert or model. A
changes.diffsentry carriesfield,fromandto.
Input example
{"companies": ["apify", "https://www.linkedin.com/company/google/"],"onlyChanges": true,"maxItems": 10}
Input
| Field | Default | What it does |
|---|---|---|
companies | ["apify"] | Company slugs or page URLs to read (up to 100). An empty input reads the sample company |
onlyChanges | false | Return only companies whose tracked fields changed since the previous run, with the old and new value. The first run for a company returns it in full |
maxItems | 10 | Maximum companies one run reads (1 to 100). A row for a company the Actor could not read counts towards it, so the run never reads more than this many companies. A company it skipped as unchanged does not count, so with onlyChanges on, a run may read the first maxItems companies and return only the changed ones. The companies after the limit are listed in OUTPUT as unchecked and cost nothing |
proxyConfiguration | Apify residential proxy | Proxy settings (country, groups, custom proxy URLs) |
Output
One row per company. With onlyChanges the row also says what moved: changedFields lists the fields and diffs carries field, from and to.
Output example
Values below are illustrative.
{"id": "1f0c2de6a4b39c88","type": "company","source": "LinkedIn public company page","status": "ok","slug": "apify","url": "https://www.linkedin.com/company/apify/","name": "Apify","description": "Thousands of Actors to automate your business, get real-time web data, and equip your AI agents.","industry": "Technology, Information and Internet","companyType": "Privately Held","companySize": "201-500 employees","employeesMin": 201,"employeesMax": 500,"headquarters": "Prague","foundedYear": 2016,"website": "https://apify.com/","followers": 46813,"specialties": ["Web scraping", "Browser automation", "AI agents"],"capturedAt": "2026-11-06T04:40:00.000Z","changes": {"baseline": false,"previousCapturedAt": "2026-11-05T04:40:00.000Z","changedFields": ["followers", "companySize"],"diffs": [{ "field": "followers", "from": 46510, "to": 46813 },{ "field": "companySize", "from": "51-200 employees", "to": "201-500 employees" }]},"errorCode": null,"errorMessage": null}
A company the Actor could not read is a row with status: "failed", its errorCode and a fixed errorMessage — never a charged row and never a missing one.
Only changes, run after run
onlyChanges keeps one record per company (its tracked field values and when the record was last written) in the named key-value store state-linkedin-company-<actor id> of your Apify account. The order matters: a record is written only after the company row was written to the dataset, so a company left out by maxItems or by the spending limit is read and returned next run, and a company that was walled or blocked keeps its old record, so the next successful run compares against the last successful one.
- First run for a company:
changes.baselineistrue,diffsis empty, the row carries the full overview. - A field changed: the row is returned,
changedFieldsanddiffsname the fields with the old and new value. - Nothing changed: no row, no charge. The run says so in its status message (
no_new_items) and OUTPUT counts the unchanged companies. - A snapshot cannot be read: the company is returned without a comparison this run, and no record is written, so a failed read never overwrites a good record.
- Do not run the same input concurrently: two runs can both see the old record and both return the same change.
How much does it cost?
LinkedIn Company Scraper uses pay-per-event pricing: you pay only for the company rows returned, not for the time it runs. At the Free tier 1,000 company rows cost $2.00; at Gold, $1.20.
| Apify plan (discount tier) | Price per 1,000 companies | Price per company |
|---|---|---|
| Free | $2.00 | $0.002 |
| Starter (Bronze) | $1.80 | $0.0018 |
| Scale (Silver) | $1.50 | $0.0015 |
| Business (Gold) | $1.20 | $0.0012 |
Apify's Free plan includes USD 5 of monthly usage, which covers about 2,500 companies at the Free tier price, run start fees aside.
- Run start fee: the platform default per run (see the Pricing tab).
- 1 company row = 1
companyevent. A status row (Authwall, refusal, 404, timeout, unreadable page) is written for visibility and is not charged. - With
onlyChanges, an unchanged company is not written and not charged, so monitoring unchanged profiles incurs zero row cost.
Use with AI agents (MCP)
LinkedIn Company Scraper works as a tool for AI agents such as Claude, Cursor and n8n agents through the Apify MCP server. Load only this Actor with this server URL:
https://mcp.apify.com?tools=kizukidata/linkedin-company-monitor
- Claude Code: run
claude mcp add apify "https://mcp.apify.com?tools=kizukidata/linkedin-company-monitor" -t http. - Claude (web or desktop app): open Customize → Connectors, choose Add custom connector, name it
Apifyand paste the server URL above. - Cursor: add the server to
~/.cursor/mcp.json(or.cursor/mcp.jsonin a project):
{"mcpServers": {"apify": { "url": "https://mcp.apify.com?tools=kizukidata/linkedin-company-monitor" }}}
- n8n: add the Apify node (on self-hosted n8n, install the community package
@apify/n8n-nodes-apify) and choose Run an Actor and get dataset; for an n8n AI Agent, add Apify Tool as a tool.
The server signs you in to Apify with OAuth. A client that cannot use OAuth can send your Apify API token in an Authorization: Bearer <APIFY_TOKEN> header instead.
What to send from an agent
Pass a small companies array (the default is the sample company) and keep maxItems small so the call returns inside the agent's timeout. Each row is a self-contained company overview, and with onlyChanges: true it also says what changed since the last run.
Integrations and API
Run the Actor from your own code or from an automation tool. Replace <APIFY_TOKEN> with your API token.
Zapier, Make and n8n
Use the Apify integration, choose Run Actor, and pass companies with onlyChanges: true. Add Get dataset items. Run the workflow on a schedule: a run with no changes returns no items, so the next step simply does not fire. Map slug, followers and changes.diffs to Slack, Airtable, Google Sheets or your CRM.
LangChain
Use description as page_content and name, slug, industry, companySize, headquarters, followers and url as metadata. ApifyDatasetLoader from the Apify LangChain integration works with the run's dataset ID; load only the changed companies by running with onlyChanges: true.
cURL
curl -X POST "https://api.apify.com/v2/acts/kizukidata~linkedin-company-monitor/runs" \-H "Authorization: Bearer <APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"companies":["apify","google"],"onlyChanges":true,"maxItems":10}'
Poll GET https://api.apify.com/v2/actor-runs/<RUN_ID> for the status, read defaultDatasetId, then fetch GET https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=json.
Python
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("kizukidata/linkedin-company-monitor").call(run_input={"companies": ["apify", "google"],"onlyChanges": True,"maxItems": 10,})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(row["slug"], row["followers"], [d["field"] for d in (row["changes"] or {}).get("diffs", [])])
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<APIFY_TOKEN>' });const run = await client.actor('kizukidata/linkedin-company-monitor').call({companies: ['apify', 'google'],onlyChanges: true,maxItems: 10,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.map((row) => `${row.name}: ${row.followers} followers`));
Limitations
- Company pages only. Employee lists, personal profiles, posts, comments and jobs are not read, and nothing is written to LinkedIn.
- Paced reads. Requests are spaced and retried automatically; if several companies in a row are refused, the run stops and lists the companies it did not reach in OUTPUT
uncheckedInputs. foundedYearis null on many pages; the Actor does not guess.- The summary is the company's own text, up to 5,000 characters; it is returned as written, not summarised.
- The employee band is LinkedIn's own band, not a headcount;
employeesMin/employeesMaxare the band bounds. - A guest page can answer with the sign-in wall (Authwall) at any time. The Actor retries twice and then reports it; it never logs in. A wall row is not charged, so if it keeps coming back, run again later.
- Two runs of the same input at the same time can both report the same change.
- Changes on the page. The reader extracts structured fields from the public page. If LinkedIn changes them, rows come back as
unexpected(not charged) and the Actor needs an update; report it in the Issues tab. - Each run writes an
OUTPUTrecord with the counts, the inputs it skipped or did not reach, and alinkedinCompanysummary (companies requested, read, failed, rows returned, changed, baseline, unchanged).
FAQ
Why is onlyChanges off by default?
Without it the Actor is a plain overview reader: every company you name comes back in full. Turn it on for scheduled monitoring, where the point is to hear about changes only.
Why did a company come back with errorCode: "authwall"?
LinkedIn answered with the sign-in wall instead of the company page. This Actor does not log in, so it reports the wall (not charged) and the next run tries again.
Why did a company come back with errorCode: "not_found" although the page exists?
LinkedIn moves a renamed page and answers the old slug with a redirect. When the slug you named now redirects to a different company, the Actor does not read that page (its rows would be another company's data), so the row says the address no longer names a company page. Use the company's current LinkedIn URL. A redirect to the renamed page of the same company is followed and read normally.
Why is foundedYear null?
The page does not show a Founded row for every company. The Actor returns what the page shows and never guesses.
Does followers change every run?
It can. That is exactly what onlyChanges reports; the follower count is one of the tracked fields, next to the employee band, the summary, industry, headquarters, founded year, website, type and specialties.
Is it legal to use this data?
The Actor reads company pages that are public to any visitor, without logging in. LinkedIn's User Agreement prohibits automated means to scrape or copy data from the service, and whether your use is permitted is your decision. If you publish the rows, keep the url link and name LinkedIn as the source. This is not legal advice.
Related Kizuki Actors
Other Actors from Kizuki that work well with this one:
- LinkedIn Jobs Scraper — the jobs those companies post, with pay and seniority.
- Google News Scraper — news about the companies you are watching.
Your feedback
Bugs, a field that stopped coming back, and feature requests go to the Actor's Issues tab in Apify Console. A company owner who wants a page left out can open an Issue with the company URL: the Actor keeps an exclusion list, and a request from a third party is not enough.