LinkedIn Profile Posts Scraper & LinkedIn Company Posts Scraper avatar

LinkedIn Profile Posts Scraper & LinkedIn Company Posts Scraper

Pricing

from $1.00 / 1,000 posts

Go to Apify Store
LinkedIn Profile Posts Scraper & LinkedIn Company Posts Scraper

LinkedIn Profile Posts Scraper & LinkedIn Company Posts Scraper

LinkedIn feed of any profile or company URL as rows — post text, a real publish timestamp to the second, likes, comments, shares, the reaction breakdown, images, video and article links, and the author. No login, no cookies. A page with nothing public is never charged.

Pricing

from $1.00 / 1,000 posts

Rating

0.0

(0)

Developer

Steadyfetch Team

Steadyfetch Team

Maintained by Community

Actor stats

0

Bookmarked

23

Total users

16

Monthly active users

1.3 hours

Issues response

3 days ago

Last modified

Share

Paste a LinkedIn company page or a person's profile and get that page's posts as rows: what was written, when it was really published, how many likes, comments and shares it has, the reaction breakdown, the images, video, document and article links attached to it, and the author. No login, no cookies, no proxy to configure. Your limit is exact and it is per page — set 50 and you get up to 50 from each link, never more, and a page holding fewer says so on a row that costs nothing. A post we could not deliver is never charged, and nothing is charged for starting a run. Click Start with nothing set and you get a built-in sample: 3 posts from one public company page, served from a frozen copy rather than fetched from LinkedIn, and nothing is charged for it.

Using an AI agent? Pin this actor in Apify's MCP server with one link: https://mcp.apify.com?tools=steadyfetch/linkedin-posts-scraper

  • Actor id: steadyfetch/linkedin-posts-scraper
  • Input: { "startUrls": ["https://www.linkedin.com/company/microsoft/", "https://www.linkedin.com/in/<public-identifier>/"] } — the one field you have to set. A company page and a person's profile can sit in the same list, each classified by its own path. Add "postsPerTarget": 50 for the per-page limit and "maxItems": 1000 for the whole run.
  • Cap the bill: set maxTotalChargeUsd on the run (a run option, not Actor input), e.g. 1.00 — the run stops when it reaches it.
  • Price: from $1.00 per 1,000 posts on Gold and above, $1.80 per 1,000 at the entry tier — one charged unit is one post delivered. No start fee, no fee for a page that returned nothing, and no second charge for the media, the article preview, the reaction breakdown or the author: they are columns on the one row you already paid for. Full table below.
  • How often it changes: a company page posts daily to weekly and a person weekly to monthly, and like and comment counts keep moving for about 72 hours before they settle — so a daily run on a company page and a weekly one on a person is the shape that fits. A re-run skips the posts your account already had, so it pays only for what is new.

Unofficial. Not affiliated with, endorsed by, or sponsored by LinkedIn or Microsoft Corporation, nor with any company or person whose public posts appear in the built-in sample.

The publish time is the real one

Read this first, because it is the one thing that separates these rows from most of the field. Every row carries postedAt — the moment LinkedIn itself stamped on the post, to the millisecond — and not a reading of a "2 weeks ago" label. You can check it yourself: the timestamp is the same epoch LinkedIn encodes inside the post's own activity id. postedAgo carries the label too, as a second column, never as the date.

What you get

One row per post, at one price.

ColumnWhat it holds
postId · postUrl · shareUrl · shareUrnthe post's own ids and its permalink
textwhat was written, in full
postedAt · postedAtTimestamp · postedAgothe real publish moment, and LinkedIn's own label beside it
authorType · authorName · authorHandle · authorUrl · authorIdwho posted it, and whether that is a person or a company
authorHeadline · authorFollowers · authorAvatarUrlthe headline on a person, the follower count on a company
likes · comments · shares · reactions[]the engagement, with the per-type reaction breakdown
countsHidden[]which counts LinkedIn is hiding on this page, so a hidden total never reads as a zero
imageUrls[] · videoUrl · videoThumbnailUrl · documentUrlthe media attached to the post
articleTitle · articleLink · articleDescriptionthe link preview, when the post shares one
isRepost · repostOfPostId · repostOfPostUrl · repostOfAuthorName · repostOfPostedAta repost, with the original underneath it
newsletterTitle · newsletterUrlwhen the post is a newsletter issue
targetUrlthe page you asked for
charged · status · statusReasonon every row, so the invoice reconciles from the dataset

Hidden counts are never zeros

LinkedIn lets a page hide its reaction, comment, repost or view counts. When it does, the number in this dataset is null and countsHidden names which one is hidden — never 0. A zero that means "we could not see it" is the same false precision as a date reconstructed from a label, and this actor does not ship either.

How often the data changes

  • A company page posts daily to weekly; a person weekly to monthly. A daily run on a company page and a weekly one on a person is usually the right shape.
  • Like and comment counts keep moving for about 72 hours after a post goes up, then settle.
  • Image, video, document and avatar links are signed by LinkedIn and expire within days. Re-run for fresh links; do not store them and expect them to keep working.
  • Re-runs skip the posts your account already had, so a repeat run pays only for what is new. That memory lives in the key-value store linkedin-posts-account in your own Apify account, and posts older than 90 days in it count as new again.
  • A page that had nothing new for your account is left alone by your runs for up to 24 hours under the same "Posted after", "Posted before" and settings: the run gives it one uncharged skipped.all_repeat row saying when it was checked and when a run reads it again, and nothing is charged for it. How long depends on "Posted after", so that a post published after the check is still inside your dates when the next read comes: with a span shorter than two days, half the span; with today, until half of what is left of the UTC day has passed; with yesterday, 12 to 24 hours; and with either of those two, every page is read again by your first run after midnight UTC. A page that gave you a new post is always read again on your next run. This holds with "Include posts you already have" on or off, and each setting keeps its own hold: with it on, posts you already have come back marked as repeats and are not charged, and a page that gave a run with it on only those counts as nothing new, so your next runs with it on leave it alone and its row says so. Pointing "Skip posts in this dataset" at a dataset reads every page once, then holds each quiet page the same way for your runs pointed at that same dataset; a different dataset reads every page again. So an hourly schedule reads each quiet page about once a day (a few times a day with today), and a daily schedule is the shape that fits. Turning on "Include posts you already have" reads a page that a run with it off left alone, and changing the dates reads every page now.
  • The memory is a key-value store in your own Apify account, so a run started with a scoped API token in restricted-access mode needs key-value store Read, Write and Create permission, or Actor runs set to Full access (Write is what lets the run remember what it delivered; without it every run pays again); without it the run says so on its status line and cannot skip what you already have.

Price

One charged unit is one post delivered. The store card shows this as from $1.00/1,000 posts — the cheapest tier, per 1,000 posts.

Apify planPer post1,000 posts
Free plan$0.0018$1.80
Bronze$0.0015$1.50
Silver$0.0012$1.20
Gold and above$0.0010$1.00

No start fee. No fee for a page that returned nothing. No second charge for the media, the article preview, the reaction breakdown or the author — they are columns on the one row you already paid for, and a repost is one post at the same price with the original underneath it.

maxTotalChargeUsd is a run option, not an input field, and it is a hard ceiling: the run stops collecting when it reaches it, writes out everything already in hand, and books the rest as rows that name the cap and cost nothing.

On the Apify free plan there is a daily allowance. One account reads at most 25 pages of posts in any 24 hours (a page is up to 50 posts from one link, so that covers a run of 25 links at the default 50 posts each), and all accounts on the Apify free plan share a daily allowance on this actor that resets at midnight UTC. Past either, the run stops cleanly: the posts it already delivered stay delivered, nothing more is read or charged, and each link it did not reach gets an uncharged skipped.free_plan_allowance row naming the reset time in UTC. Paid Apify plans carry no daily allowance.

Honest rows

Nothing below is charged, and every one of them arrives as a row you can read rather than as a missing line. The row's status is the first column; statusReason is the sentence.

statusWhat the row says
profile_not_foundLinkedIn does not list a public page at this URL, or it cannot be read without a login — nothing was charged for it.
page_not_foundThe same answer on a company or showcase page: LinkedIn does not list one publicly at this URL.
no_dataThis page exists and LinkedIn shows no public posts on it — nothing was charged.
skipped_date_windowThis page has public posts, but none of the ones LinkedIn lists fall inside your dates — widen "Posted after" or "Posted before" to collect them. Nothing was charged for the posts it did not deliver, and a run with the same dates finds the same.
skipped.all_repeatThe page reached posts your account already had. LinkedIn lists posts newest first, so the rest are older than those, and the run read no further page for this link. Nothing was charged for the posts it did not deliver; the row says how to collect older ones. The same status marks a page that had nothing new for your account when it was checked in the last 24 hours under the same dates and the same "Include posts you already have" setting, so it was not read again: that row says when it was checked and when a run reads it again.
skipped.page_capThe walk reached the 200 pages this actor reads for one link and LinkedIn was still serving — that bound is this actor's own, not a verdict about the page, so one link can never spend a whole run. The row says what to change. Nothing was charged for the posts it did not deliver.
input_errorThe link is not one this actor can read. A link to a single post, an old /pub/ profile link, a Sales Navigator link, or a short link that could not be followed each says so and names what to paste instead, and every such row lists the link shapes that work. The run's record keeps the field the link arrived in and the reason, never what you typed.
feed_unavailableLinkedIn did not answer for this page on this run. Please re-run — nothing was charged. If posts had already been delivered before it stopped answering, the row opens with how many and what they cost, and the re-run is for the rest.
vendor_out_of_credit · vendor_budgetThis run reached its own data budget (the row says how to continue in a new run), or the data feed behind this actor is paused; nothing was charged.
skipped_max_items · skipped_budget · skipped_deadlineOne of your own limits or the run clock stopped the run first, and the row names which.
skipped.free_plan_allowanceOn the Apify free plan only: the run reached the plan's daily allowance on this actor (see Price) before this link. The row says when it resets, in UTC; paid Apify plans carry no daily allowance.

Posts your account already had are skipped rather than delivered twice, and are never charged either. Because LinkedIn lists posts newest first, reaching them means the rest of that page's feed is older than what you already have, so the run reads no further page for that link — a re-run pays only for what is new and never for pages of posts you hold. A run pointed at a dataset with "Skip posts in this dataset", the way to pick up where a stopped run left off, still reads past them to the older posts that run never reached. To collect older posts otherwise, turn on "Include posts you already have" (they come back marked as repeats, not charged, and a page that gives a run with it on nothing but repeats is not read again by your runs with it on for up to 24 hours) or set "Posted before". All of this holds unless the token that started the run cannot open key-value stores (see the scoped-token note above), and then the run says so on its status line, on a note row and on every row it charged.

A person's profile (/in/<name>/), a company or showcase page (/company/<name>/, /showcase/<name>/) and a school page (/school/<name>/). A mobile link to one of those, and a lnkd.in short link that leads to one, are followed to that page; tracking parameters and a country subdomain make no difference.

A link to one post is not this actor's door

This actor reads a PROFILE or a COMPANY page and returns that page's posts. A link to a single post — /feed/update/… or /posts/…-activity-… — comes back as an uncharged row telling you to paste the author's page instead.

Use it as an API endpoint (Standby)

You can also call this actor like an API: send up to five profile or company page links and get their latest posts back in the same response, with no run to start and no dataset to read. The address is https://steadyfetch--linkedin-posts-scraper.apify.actor, and the actor's Endpoints tab lets you try it from the browser.

curl -H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \
"https://steadyfetch--linkedin-posts-scraper.apify.actor/?startUrls=https://www.linkedin.com/company/microsoft/&postsPerTarget=20"
SettingWhat it does
startUrlsA profile or company page link. Repeat it for more links: up to 5 per request (1 on the Apify free plan). profileUrls and companyUrls work as they do on a run.
postsPerTargetHow many of the latest posts to return from each link. 50 if you leave it out; at most 100 per link per request (25 on the Apify free plan).
maxItems, postedAfter, postedBefore, includeRepostsThe same settings as on a run, read the same way.

A POST with the same fields as a JSON body works too. The answer is JSON: rows (the same rows a run writes to its dataset, the run summary last), delivered, charged, and notes for anything that was not returned, in plain words. Each request is charged exactly as a run with the same input: per post returned, and the per-page check where a run would charge it. If the charge for a request cannot be completed, its posts are not sent and nothing is charged.

Good to know: the endpoint has no account memory, so it does not skip posts you already have — every request returns the posts it reads. For long lists, to skip posts you already collected, or to read "Skip posts in this dataset", run the actor as usual.

Other scrapers you might want

Limits and good manners

Only public pages are returned — a page behind a login is an uncharged row, not a workaround. This actor may stop working if LinkedIn changes how the data is served; if it does, items that fail are never charged.

Support

Something off, or a column you need that is not here? Open an issue on the Issues tab — we usually reply within a couple of hours.

If it earned its keep, a rating helps other buyers find it, and saving the actor keeps it one click away.