LinkedIn Post Scraper - $0.90 per 1,000, No Login avatar

LinkedIn Post Scraper - $0.90 per 1,000, No Login

Pricing

from $0.90 / 1,000 validated public posts

Go to Apify Store
LinkedIn Post Scraper - $0.90 per 1,000, No Login

LinkedIn Post Scraper - $0.90 per 1,000, No Login

Scrape LinkedIn posts from a public profile URL. The LinkedIn feed needs an account. But a member's posts also sit on their public profile page. Each row has the post text, author, image, publish time and the post URL. No login, no cookies. Empty searches cost nothing. $0.90 per 1,000 posts.

Pricing

from $0.90 / 1,000 validated public posts

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

2

Monthly active users

43 minutes ago

Last modified

Share

LinkedIn Profile Posts Scraper: recent public posts from a person's profile

Give it a public /in/ profile URL and get back the posts LinkedIn links from that page: the post URL, the activity id, the author, the headline text of the post, the image and the publish time when the page states one. You can also hand it post URLs directly and skip the discovery step.

The honest part first. This reads the logged-out version of a profile, and LinkedIn only links a handful of recent posts there. It is a window on what somebody has been posting lately, not an archive of everything they have ever written.

InputPublic /in/ profile URLs, public /posts/ URLs, or both
OutputOne row per post
Ceiling100 posts per run, 25 per profile
Account neededNone
Price$0.90 per 1,000 posts, flat on every plan

📰 What LinkedIn Profile Posts Scraper does

The LinkedIn feed needs an account. Individual post pages do not: LinkedIn publishes them for search engines, and links some of them from the public profile page.

So the run works in two steps. It opens each profile you gave it and collects the post links on that page, keeping only posts by that person. Then it opens each post page and reads what the page publishes about itself: the title line, the preview text, the image and, if the page states one, the publish time. Post URLs you supplied yourself are fetched first, before anything discovered from a profile.

Every post page has to agree that it is the post you asked for, checked on the canonical URL and the activity id in it. A repost or a redirect that lands on a different activity is reported rather than written as a row, so you never get one post's text filed under another post's id.

📥 What you give it

{
"profileUrls": ["https://www.linkedin.com/in/reidhoffman/"],
"maxPostsPerProfile": 10,
"maxPosts": 25
}
FieldDefaultWhat it is
profileUrlsemptyUp to 20 public /in/ URLs. The run reads the posts linked from each one.
postUrlsemptyUp to 100 direct /posts/...activity-... URLs, when you already know the posts you want. A feed/update/urn:li:activity link is refused, so convert it to the /posts/ form first.
maxPostsPerProfile101 to 25. How many posts to take from each profile.
maxPosts251 to 100. The ceiling for the whole run, direct URLs and discovered posts together.
requestTimeoutSecs205 to 60 seconds. How long to wait for one page.

Leave both URL fields empty and you get a single labelled sample row, free.

Two caps, and the lower one wins. Ten profiles at maxPostsPerProfile: 25 is 250 candidate posts, but maxPosts: 25 stops the run at 25. Raise both if you want more.

Watch the clock on big runs. Profiles and posts are fetched one at a time, and the run ends at the timeout on the actor's Settings tab, 180 seconds unless you raise it. Twenty profiles plus a hundred posts will not fit in that.

📤 What you get back

A real row from a recent run, with the image link cut short:

{
"ok": true,
"_sample": false,
"sourceType": "public_linkedin_post",
"postUrl": "https://www.linkedin.com/posts/reidhoffman_your-family-needs-a-cybersecurity-plan-activity-7503529382813143041--ub-",
"activityId": "7503529382813143041",
"sourceProfileUrl": "https://www.linkedin.com/in/reidhoffman",
"authorPublicIdentifier": "reidhoffman",
"authorName": "Reid Hoffman",
"title": "Your family needs a cybersecurity plan. | Reid Hoffman | 111 comments",
"content": "Open-source tools can now turn a single image into a live face swap on consumer hardware, while agents are lowering the cost of far more sophisticated attacks. ... | 111 comments on LinkedIn",
"imageUrl": "https://media.licdn.com/dms/image/v2/D5612AQFZNnO9R5UHvQ/article-cover_image-shrink_720_1280/...",
"publishedAt": null,
"transport": "direct_http",
"retrievedAt": "2026-09-14T05:45:38.560Z"
}
FieldWhat it is
activityIdThe digits at the end of the post URL. The stable key for a post, and the right thing to dedupe on.
contentThe page's own preview text. Look at the row above: it is the post, but LinkedIn trims long ones and glues | N comments on LinkedIn onto the end. Strip that tail yourself if it gets in the way.
titleThe page title line. Author and comment count are usually part of it.
authorNameSplit out of that title line, so a post whose own text contains a vertical bar can put a fragment of the text here instead of the name. authorPublicIdentifier comes from the URL and is the safer field.
sourceProfileUrlThe profile this post was found on, or null when you supplied the post URL yourself.
publishedAtThe publish time when the page states one, null when it does not. It often does not, as in the row above.

🧾 Reading the output

Three kinds of row, and only real posts cost anything.

RowHow to spot itCharged
A postsourceType: "public_linkedin_post"yes
The sample row_sample: true, and it only appears when you run with empty inputno
A diagnosticok: false and _diagnostic: trueno

There is no charged field on these rows. sourceType is what separates a real post from a sample or a diagnostic.

A diagnostic row carries an errorCode:

CodeWhat it means
BAD_INPUTNot a public /in/ or /posts/...activity-... URL. Nothing was requested for it.
NO_RESULTSFor a profile: LinkedIn linked no posts of that person's own on the public page. For a post: the page that answered was a different activity, usually a repost or a redirect.
BLOCKEDLinkedIn answered with a challenge page instead of the content. Other URLs in the same run still go ahead.
RATE_LIMITEDToo many pages too close together. Space your runs out.
SERVER_ERRORLinkedIn returned an error of its own.
NETWORKThe page did not arrive inside requestTimeoutSecs, or LinkedIn answered with something unusable. A deleted post shows up here rather than under a "not found" code.

Neither a sample nor a diagnostic row fails the run.

▶️ How to run it

  1. Open LinkedIn Profile Posts Scraper and click Try for free.
  2. Paste profile URLs into Public LinkedIn profile URLs, or post URLs into Public LinkedIn post URLs.
  3. Set Maximum posts per profile and Maximum total posts.
  4. Click Start.
  5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

💰 How much does it cost?

$0.90 per 1,000 posts. Flat on every Apify plan, no volume tiers.

One charge per post row. Sample rows and diagnostic rows are never charged, and a profile that turns out to have no public posts costs you nothing for results.

One thing to know about duplicates: the run skips a post URL it has already queued, matched on the URL text. Two different spellings of the same post, which LinkedIn does produce, read as two posts and are fetched and charged twice. Dedupe your input list on activity-<digits> and you will not hit it.

💡 What people use it for

  • Seeing what a prospect has posted recently before writing to them.
  • Watching a handful of people in your market and picking up the themes they keep returning to.
  • Collecting your own posts for a report, without exporting anything from LinkedIn.
  • Pulling the post text and image behind a link somebody shared with you.

🚧 What it does not do

  • No post archive. Only the posts LinkedIn links from the logged-out profile page, which is a recent handful. There is no paging back through someone's history.
  • No reaction or comment counts as numbers. The count is sometimes inside the title text, but there is no field to sort on.
  • No comments. Use the comments actor below for those.
  • No private, connection-only or deleted posts, and no posts from a profile that is not public.
  • The text can be a preview. content is what the page publishes about itself, so a long post arrives trimmed by LinkedIn, not by this actor.
  • No video files or document attachments. One image link at most.
  • No retries. A page that fails, fails for that run.

🧭 Which LinkedIn scraper do you need?

If you wantUse
Recent posts from a person's profileThis one
Posts matching a keyword, from anyoneLinkedIn Post Search Scraper
Posts from a company pageLinkedIn Company Posts Scraper
The comments under a postLinkedIn Post Comments Scraper
The person's profile detailsLinkedIn Profiles Scraper

❓ Questions people ask

Do I need a LinkedIn account? No, and there is no cookie field. Nothing to paste, nothing to renew.

Why did I only get a few posts from a profile? Because that is how many LinkedIn links on the public page. Raising maxPostsPerProfile does not make more of them appear.

Can I get posts from a date range? Not from here. Dates are missing on many public post pages, so there is nothing reliable to filter on.

Can I give it a feed/update/urn:li:activity link? Not directly. Open the post, copy the /posts/... URL from the address bar and use that.

Is scraping LinkedIn legal? This reads only pages LinkedIn publishes to the open web for search engines. Posts can contain personal data, which GDPR and similar laws cover, so have a lawful reason for collecting it. Apify's write-up on scraping and the law is a reasonable starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the run ID and the profile or post URL that went wrong. The errorCode on the diagnostic row usually explains it on its own.