LinkedIn Post Scraper - $0.90 per 1,000, No Login
Pricing
from $0.90 / 1,000 validated public posts
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
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
2
Monthly active users
43 minutes ago
Last modified
Categories
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.
| Input | Public /in/ profile URLs, public /posts/ URLs, or both |
| Output | One row per post |
| Ceiling | 100 posts per run, 25 per profile |
| Account needed | None |
| 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}
| Field | Default | What it is |
|---|---|---|
profileUrls | empty | Up to 20 public /in/ URLs. The run reads the posts linked from each one. |
postUrls | empty | Up 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. |
maxPostsPerProfile | 10 | 1 to 25. How many posts to take from each profile. |
maxPosts | 25 | 1 to 100. The ceiling for the whole run, direct URLs and discovered posts together. |
requestTimeoutSecs | 20 | 5 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"}
| Field | What it is |
|---|---|
activityId | The digits at the end of the post URL. The stable key for a post, and the right thing to dedupe on. |
content | The 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. |
title | The page title line. Author and comment count are usually part of it. |
authorName | Split 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. |
sourceProfileUrl | The profile this post was found on, or null when you supplied the post URL yourself. |
publishedAt | The 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.
| Row | How to spot it | Charged |
|---|---|---|
| A post | sourceType: "public_linkedin_post" | yes |
| The sample row | _sample: true, and it only appears when you run with empty input | no |
| A diagnostic | ok: false and _diagnostic: true | no |
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:
| Code | What it means |
|---|---|
BAD_INPUT | Not a public /in/ or /posts/...activity-... URL. Nothing was requested for it. |
NO_RESULTS | For 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. |
BLOCKED | LinkedIn answered with a challenge page instead of the content. Other URLs in the same run still go ahead. |
RATE_LIMITED | Too many pages too close together. Space your runs out. |
SERVER_ERROR | LinkedIn returned an error of its own. |
NETWORK | The 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
- Open LinkedIn Profile Posts Scraper and click Try for free.
- Paste profile URLs into Public LinkedIn profile URLs, or post URLs into Public LinkedIn post URLs.
- Set Maximum posts per profile and Maximum total posts.
- Click Start.
- 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
titletext, 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.
contentis 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 want | Use |
|---|---|
| Recent posts from a person's profile | This one |
| Posts matching a keyword, from anyone | LinkedIn Post Search Scraper |
| Posts from a company page | LinkedIn Company Posts Scraper |
| The comments under a post | LinkedIn Post Comments Scraper |
| The person's profile details | LinkedIn 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.