# Truth Social Scraper - Posts, Profiles, Monitor (no login) (`datahamster/truth-social-posts`) Actor

Truth social scraper for public accounts: one flat row per post with text, media, replies, reposts and likes, plus an optional profile row with followers and post counts. No login, no API token. Monitor mode alerts on new posts and engagement changes. $2 per 1,000 rows, empty runs cost nothing.

- **URL**: https://apify.com/datahamster/truth-social-posts.md
- **Developed by:** [Viktor Dubnytskiy](https://apify.com/datahamster) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 result items

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Truth Social Scraper - Posts, Profiles, Monitor (no login)

Scrape public Truth Social accounts and get one flat row per post: text, media, reply/repost/like counters, timestamps and the permalink. Add a profile row with followers and post counts when you need the account card too. No login, no cookies, no API token - the actor reads the same public JSON the site serves to a logged-out visitor.

### What you get

One row per post: `id`, `url`, `postId`, `accountId`, `username`, `displayName`, `text`, `contentHtml`, `createdAt`, `repliesCount`, `repostsCount`, `likesCount`, `mediaUrls`, `mediaTypes`, `isReply`, `isRepost`, `repostOfPostId`, `repostOfUsername`, `language`, `query`, `source`, `scrapedAt`.

With **Add a profile row** on, each account also returns one `kind: "account"` row: `followersCount`, `followingCount`, `statusesCount`, `bio`, `bioHtml`, `verified`, `avatarUrl`, `headerUrl`, `website`, `location`, `accountCreatedAt`, `lastStatusAt`.

`text` is the post with the HTML stripped; `contentHtml` keeps the original markup so links and mentions survive.

### Example output

Real rows from the example dataset (`accounts: ["realDonaldTrump", "TeamTrump"]`):

| Field | Example value |
|---|---|
| `url` | `https://truthsocial.com/@realDonaldTrump/117257273512193853` |
| `text` | `Such a great golfer. Too bad I have very little time to play!!!` |
| `createdAt` | `2026-09-12T09:06:42.567Z` |
| `likesCount` / `repostsCount` / `repliesCount` | `13212` / `2475` / `2580` |
| `mediaTypes` / `mediaUrls` | `["video"]` / `https://static-assets-1.truthsocial.com/.../b53a5f0680834206.mp4` |
| `username` / `displayName` | `realDonaldTrump` / `Donald J. Trump` |
| account row | `followersCount: 13048752`, `statusesCount: 36561`, `verified: true`, `website: www.DonaldJTrump.com` |

### Use cases

- Track what a public figure or campaign account posts and how fast each post gains likes and ReTruths.
- Build a dataset of posts for media monitoring, research or sentiment work, with media URLs attached.
- Watch a set of accounts in monitor mode and get a webhook or Telegram alert on every new post.

### Input

| Field | Meaning | Default |
|---|---|---|
| `accounts` | Handles, @handles or profile URLs | `["realDonaldTrump"]` |
| `maxPostsPerAccount` | Posts per account, newest first (1-5000) | `100` |
| `includeReplies` | Keep the account's replies | `false` |
| `includeReposts` | Keep reposts (ReTruths) | `false` |
| `sinceDate` | Stop at the first post older than this date | empty |
| `includeAccountRow` | Add one profile row per account | `false` |
| `maxItems` | Stop after this many rows | `100` |
| `mode` | `scrape` or `monitor` (only new/changed since last run) | `scrape` |
| `monitorKey`, `webhookUrl`, `telegramBotToken`, `telegramChatId` | Monitor-mode state key and alert targets | empty |

### Pricing

| Event | Price |
|---|---|
| result | $0.002 per row ($2 per 1,000) |
| monitor-check | $0.006 per monitor run |
| change | $0.002 per new or changed post |

You are charged only for rows actually pushed: a run that finds nothing charges no result events. Truth Social answers only through Apify's **Web Unblocker** proxy, whose traffic is billed by Apify on top of these events.

### Monitor mode

Set `mode: "monitor"` on a saved task and each run returns only posts that are new or whose like, repost or reply counts changed since the previous run. A webhook URL or a Telegram bot token plus chat id turns that into an alert.

### Limits

- Keyword search (`/api/v2/search`), trending posts (`/api/v1/trends`) and hashtag timelines need a logged-in account: checked from the platform on 2026-09-12, the first two answer `401 USER_UNAUTHENTICATED` and the hashtag timeline answers an empty list to every logged-out request. This actor therefore scrapes accounts, not keywords.
- Public accounts only. A locked account, a deleted account or an unknown handle is skipped and returns no rows.
- Truth Social answers only through Apify's Web Unblocker, and every page of 20 statuses is one billed request. `includeReplies: false` and `includeReposts: false` drop rows *after* fetching them, so a heavily filtered account reads more pages than the rows it returns; each account stops at 300 pages (6,000 statuses scanned) whatever the filters say.
- Counters are the values at scrape time; a fresh post's counts move for hours afterwards.
- No follower lists, no likers, no repliers - the actor returns the account's own public posts and its public profile card.

### FAQ

**Do I need a Truth Social account, cookies or a bearer token?** No. There is no credential field at all; every request is a logged-out public API call.

**Why is `text` empty on some rows?** Those posts are media-only (a picture or video with no caption). `mediaUrls` and `mediaTypes` still carry the attachment.

**What does a repost row look like?** With `includeReposts: true` a ReTruth keeps the reposting account's row identity (`postId`, `url`, `username`) and carries the original post's text, media and counters, plus `repostOfUsername` and `repostOfPostId` for attribution.

**What happens when there are no results?** No rows are pushed and no result events are charged. The `RUN_SUMMARY` record in the run's key-value store carries `emptyReason`, which separates "the handle does not exist" from "the site answered with a wall".

### Changelog

- 0.1: initial release - accounts and posts through the public JSON API, profile rows, reply/repost/date filters, monitor mode; auth walls are reported as blocks instead of empty datasets.

***

If this actor saved you time, a short review on its Store page genuinely helps other people find it. Found a bug or need a field that is missing? Open a ticket on the **Issues** tab.

# Actor input Schema

## `maxItems` (type: `integer`):

Stop after this many results (you are charged only for pushed items)

## `mode` (type: `string`):

scrape = full results; monitor = only new/changed items since the previous run of this task

## `monitorKey` (type: `string`):

Optional state key when not running as a saved task

## `webhookUrl` (type: `string`):

POST a change summary here in monitor mode

## `telegramBotToken` (type: `string`):

Optional: bot token for monitor-mode change summaries

## `telegramChatId` (type: `string`):

Optional: chat id that receives monitor-mode summaries

## `accounts` (type: `array`):

Public Truth Social accounts to scrape, one per line. A handle ("realDonaldTrump"), an @handle ("@TeamTrump") or a profile URL ("https://truthsocial.com/@TeamTrump") all work.

## `maxPostsPerAccount` (type: `integer`):

How many posts to take from each account, newest first, e.g. 100. The overall run still stops at Max items, and each account reads at most 300 pages (6,000 statuses) however tight the filters are. Range 1-5000.

## `includeReplies` (type: `boolean`):

true = keep the account's replies to other posts as rows (`isReply: true`). false = only the account's own posts. Filtering costs extra: replies and reposts are dropped after they are fetched, so a filtered run reads more pages (more billed Web Unblocker requests) than the number of rows you keep. Example: false.

## `includeReposts` (type: `boolean`):

true = keep reposts (ReTruths) as rows carrying the original post's text, media and counters plus `repostOfUsername`. false = only original posts. Like Include replies, filtering drops rows after fetching them, so a filtered run reads more pages and bills more Web Unblocker requests than the rows kept. Example: false.

## `sinceDate` (type: `string`):

Stop at the first post older than this date, e.g. "2026-09-01" or "2026-09-01T12:00:00Z". Leave empty to go back as far as Max posts per account allows.

## `includeAccountRow` (type: `boolean`):

true = emit one extra row per account (`kind: "account"`) with followers, following, post count, bio, website and verification. false = posts only. Example: true.

## Actor input object example

```json
{
  "maxItems": 100,
  "mode": "scrape",
  "accounts": [
    "realDonaldTrump"
  ],
  "maxPostsPerAccount": 100,
  "includeReplies": false,
  "includeReposts": false,
  "includeAccountRow": false
}
```

# Actor output Schema

## `results` (type: `string`):

All pushed rows (dataset, JSON)

## `resultsTable` (type: `string`):

Dataset in the Console viewer

## `runSummary` (type: `string`):

RUN\_SUMMARY record

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "accounts": [
        "realDonaldTrump"
    ],
    "maxPostsPerAccount": 100,
    "sinceDate": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("datahamster/truth-social-posts").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "accounts": ["realDonaldTrump"],
    "maxPostsPerAccount": 100,
    "sinceDate": "",
}

# Run the Actor and wait for it to finish
run = client.actor("datahamster/truth-social-posts").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "accounts": [
    "realDonaldTrump"
  ],
  "maxPostsPerAccount": 100,
  "sinceDate": ""
}' |
apify call datahamster/truth-social-posts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datahamster/truth-social-posts"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/pszmdheV17mR6hEZo/builds/lwgWWm1HcH3TpZLzk/openapi.json
