Truth Social Scraper: Posts & Profiles
Pricing
from $4.00 / 1,000 post scrapeds
Truth Social Scraper: Posts & Profiles
Scrape Truth Social posts and profiles without a login. Paste usernames or post URLs and get every post with likes, reblogs, replies, upvotes and downvotes, edits, media, quotes and link cards, plus full profile details. Filter by date, skip replies or reblogs. Export to CSV, Excel or JSON.
Pricing
from $4.00 / 1,000 post scrapeds
Rating
0.0
(0)
Developer
CHEN-SHU-CHEN
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
What is Truth Social Scraper?
You want to know what an account posted on Truth Social, when, and how people reacted: for a news story, a research dataset, a monitoring sheet. The site has no export, and copying posts by hand loses the numbers and the edits.
Paste Truth Social usernames or profile URLs and get every post as a row: the text, the exact replies, reblogs (ReTruths), likes, upvotes and downvotes, when it was posted and when it was last edited, its images and videos, the post it quotes or reshares, link previews, mentions and hashtags. Each profile also comes back as a row of its own: followers, following, post count, bio, website, join date, and whether the account is verified or premium. You can also paste single post URLs.
No Truth Social account or login is needed.
Because it runs on Apify, you can schedule a daily pull of an account's new posts, call it through the API, connect it to Make, Zapier or Google Sheets, and export the table as CSV, Excel or JSON.
How to scrape Truth Social posts
- Open the Input tab and paste usernames or profile URLs into Profiles, one per line.
realDonaldTrump,@realDonaldTrumpandhttps://truthsocial.com/@realDonaldTrumpall work. - Set Maximum posts per profile. Posts come newest first. Set it to 0 to get only the profile rows.
- Optional: limit the posts to a date window with Posts from and Posts until, and skip replies, reblogs or posts without media.
- Optional: paste single posts into Post URLs.
- Click Start. A profile with 100 posts takes about five seconds.
- Open the Output tab. The dataset has two tables, Posts and Profiles; export either one, or everything.
How much does it cost to scrape Truth Social?
You pay per row delivered, and nothing for rows that failed.
| Event | Price | Per 1,000 |
|---|---|---|
Post scraped (post-scraped) | $0.004 | $4 |
Profile scraped (profile-scraped) | $0.004 | $4 |
Run start (apify-actor-start, per GB of memory) | set by Apify | — |
So one profile with its 100 newest posts costs about $0.40. Usernames that do not exist, invalid input, posts that were deleted, and anything the run did not get to are free. Apify's free plan ($5 a month) covers about 1,250 rows.
A post is charged once per run. If a post URL you pasted was already returned from a profile's feed in the same run, it is not repeated and not charged again.
How do I cap what a run can spend?
Set a maximum cost per run in the run options. Each row is written and charged in one step, and the run stops on the first row the limit cannot pay for, so you never pay more than the limit and never pay for a row you did not get. A profile's own row is kept room for while its posts are read, so the posts never use up the money its profile row needs. The profiles and posts it did not reach still appear in the output with the status not_processed, free. The profile it stopped on says charge_limit in postsStopReason.
Input
| Field | Description |
|---|---|
profiles | Usernames or profile URLs. Each gives one profile row and up to maxPostsPerProfile post rows |
maxPostsPerProfile | Newest first; 0 for profile rows only. Default 20 |
postsSince, postsUntil | Optional date window, in UTC. 2026-10-01, an ISO date-time, or a relative date such as 7 days (meaning 7 days ago). A bare date in postsUntil includes that whole day |
excludeReplies | Leave out replies, the account's own threads included |
excludeReblogs | Leave out reblogs (ReTruths). Quote posts are kept |
onlyPostsWithMedia | Only posts with at least one image or video |
postUrls | Single posts: https://truthsocial.com/@user/117461843705117717, the /posts/ form, or the bare numeric ID |
proxyConfiguration | Apify datacenter proxy by default |
residentialFallback | If Cloudflare keeps blocking the datacenter proxy, finish the run on Apify's US residential proxy. On by default; included in the price |
A post URL pasted into Profiles is read as a post, and a profile URL pasted into Post URLs as a profile.
Example input:
{"profiles": ["realDonaldTrump", "https://truthsocial.com/@DonaldJTrumpJr"],"maxPostsPerProfile": 100,"postsSince": "2026-10-01","excludeReblogs": true,"postUrls": ["https://truthsocial.com/@realDonaldTrump/117461843705117717"]}
Output
Every row has a type (post or profile), a status, an error message when something went wrong, and the input line it came from. Statuses: ok, not_found, login_required, blocked, rate_limited, error, parse_error, invalid_input, not_processed. One row per input at least, so 50 profiles in means 50 profile rows out, whatever happened to them.
A profile's posts are written before its profile row, so the profile row can say how many posts came with it.
Post rows
| Field | Notes |
|---|---|
id, url, uri | |
createdAt, editedAt, version | ISO 8601, UTC. editedAt is null for a post never edited; version counts the edits |
title | Set on some posts (Truth Social's own field); usually null |
content, text | The post as HTML, and as plain text with line breaks kept |
language, visibility, sensitive, spoilerText | |
repliesCount, reblogsCount, favouritesCount | Exact counts. favouritesCount is the like count |
upvotesCount, downvotesCount | Truth Social's vote counts |
isReply, isReblog, isQuote | |
inReplyToId, inReplyToAccountId, inReplyTo | inReplyTo is the parent post, when the API includes it |
quoteId, quote | The quoted post, with its own text, counts, media and author |
reblog | For a reblog, the original post, with its own counts and author |
mediaCount, mediaAttachments | Each with type (image, video, gifv, audio), url, previewUrl, width, height, aspectRatio, durationSeconds, bitrate, frameRate, description (alt text), blurhash |
card | The link preview: url, title, description, imageUrl, providerName, authorName, embed html |
poll | Options with vote counts, expiresAt, votersCount |
mentions, tags, hashtags, emojis | |
group | For posts made in a Truth Social group |
sponsored | true for a promoted post |
authorUsername, authorDisplayName, authorVerified, authorPremium, authorFollowersCount | Shortcuts for the table view |
account | The author's full profile, the same fields as a profile row |
scrapedAt | When the row was read |
Example post row (shortened):
{"type": "post","status": "ok","input": "realDonaldTrump","id": "117461843705117717","url": "https://truthsocial.com/@realDonaldTrump/117461843705117717","createdAt": "2026-10-18T12:11:35.989Z","editedAt": null,"text": "France is burning! The immigration of people from an entirely different world…","repliesCount": 1123,"reblogsCount": 2734,"favouritesCount": 11720,"upvotesCount": 11720,"downvotesCount": 0,"isReply": false,"isReblog": false,"isQuote": false,"mediaAttachments": [],"authorUsername": "realDonaldTrump","authorVerified": true,"authorPremium": true,"authorFollowersCount": 13121258}
Profile rows
| Field | Notes |
|---|---|
id, username, acct, displayName, url | |
bio, bioText | HTML and plain text |
website, location, fields | fields are the extra name/value lines some profiles show |
avatarUrl, avatarStaticUrl, headerUrl, headerStaticUrl | |
followersCount, followingCount, statusesCount | Exact. statusesCount is the account's total posts |
createdAt, lastStatusAt | Join date-time, and the date of the latest post |
verified, premium | Blue check, and Truth+ |
locked, bot, isGroup, discoverable, acceptingMessages, acceptsChatMessages, tvAccount | |
postsScraped | How many post rows this run returned for the profile |
postsStopReason | Why it stopped: max_posts, date_range, end_of_feed, charge_limit, charge_failed, time_budget, spend_guard (the run was costing more than it earned), or the status of a feed page that failed |
postsError | The error, when a feed page failed |
The key-value store also holds RUN_SUMMARY: rows delivered, failed, skipped as duplicates and not processed, the number of requests, and why the run stopped if it stopped early.
FAQ
Do I need a Truth Social account?
No. Everything comes from what Truth Social shows any logged-out visitor, through the same public API its website uses.
What can it not get?
These need a logged-in account on Truth Social, so they are not offered:
- Search for posts or accounts by keyword or hashtag, and trending posts
- Followers and following lists
- Who liked or reblogged a post
- Reply threads under a post. Each post's reply count is included, and a reply you scrape carries the post it answers
- Groups' own feeds. Group posts that appear on a profile are included, with their
group
Private (locked) accounts show their profile but not their posts. Their profile row is returned with postsScraped: 0, and postsStopReason says what the feed answered. Deleted and suspended posts or accounts come back not_found.
Is it legal to scrape Truth Social?
It reads only public posts and profiles, without logging in. Posts are personal data under laws such as the GDPR when they identify a person, so check what applies to your use. This is not legal advice.
Why is a username not found?
Check the spelling; case does not matter. An account that was deleted or suspended also comes back not_found. These rows are free.
How fast is it, and are there limits?
A feed page holds 20 posts and takes well under a second, so 1,000 posts take about a minute. Truth Social allows 300 profile lookups per five minutes; the run waits for the reset rather than hitting the limit, so very long lists of profiles slow down after the first 300.
What happens when Cloudflare blocks the run?
Truth Social is behind Cloudflare. The run reads the API with a browser's network fingerprint, so it is normally let through. If a request is blocked anyway, it is retried on a fresh IP; after repeated blocks the run moves to Apify's US residential proxy for the rest of the run, at no extra charge to you. If it is still blocked, the affected rows come back blocked, and after four inputs in a row fail this way the run stops and marks the rest not_processed, free.
Why are the rows for one profile split into two tables?
Apify shows a dataset through views. Posts and Profiles are two views of the same dataset; each shows its own columns, and rows of the other type appear in it with those columns empty. Filter on type in your spreadsheet, or export a view as CSV.
Something broke or a number looks wrong
Open an issue on the Issues tab with the input and the run link. Reports are answered there.