# X (Twitter) Posts Scraper (`guezi/x-profile-posts-scraper`) Actor

Collect public posts from any X (Twitter) account with likes, reposts, replies, quotes, bookmarks and view counts on every row, plus images, videos, hashtags and links. Filter by date, engagement, language or media. No X account or login needed. Export to CSV, Excel, JSON or Sheets.

- **URL**: https://apify.com/guezi/x-profile-posts-scraper.md
- **Developed by:** [Kawtar](https://apify.com/guezi) (community)
- **Categories:** Social media, News
- **Stats:** 3 total users, 2 monthly users, 95.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.40 / 1,000 post scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## X (Twitter) Posts Scraper

Collect the public posts of any X (Twitter) account — with likes, reposts,
replies, quotes, bookmarks and view counts on every row, plus images, video
links, hashtags, mentions and outbound links. Give it a list of accounts and a
few filters, and it returns a clean, analysis-ready table. No X account, no
login, and no browser extension needed.

### What you can do with it

- **Track competitors and category leaders.** Pull everything a set of accounts
  posted this month and see which messages actually travelled.
- **Build a content swipe file.** Filter to posts above a view or like threshold
  and study only the winners.
- **Feed dashboards and reports.** Export to CSV, Excel, JSON or Google Sheets,
  or pull the results straight into your own systems.
- **Monitor announcements.** Schedule a daily run over the accounts you care
  about and collect anything new.
- **Research a topic through the people who own it.** Point it at the accounts
  that matter in your niche and analyse language, cadence and links.
- **Collect media at source.** Grab the full-resolution images and the best
  available video files attached to posts.

### What you get

One row per post:

```json
{
  "postId": "2082878156483219672",
  "url": "https://x.com/OpenAI/status/2082878156483219672",
  "text": "We are committed to pushing the model frontier across cost efficiency…",
  "createdAt": "2026-07-30T17:17:05.000Z",
  "language": "en",
  "likes": 19480,
  "reposts": 1963,
  "replies": 1363,
  "quotes": 1841,
  "bookmarks": 2686,
  "views": 16337771,
  "isRepost": false,
  "isReply": false,
  "isQuote": false,
  "isPinned": true,
  "hashtags": [],
  "mentions": [],
  "links": [],
  "media": [
    {
      "type": "photo",
      "imageUrl": "https://pbs.twimg.com/media/HOfepUra4AAUEZi.png?format=png&name=orig",
      "width": 1632,
      "height": 1274
    }
  ],
  "postedVia": "Typefully",
  "profile": {
    "username": "OpenAI",
    "displayName": "OpenAI",
    "followers": 5086994,
    "following": 4,
    "postCount": 2048,
    "hasSubscriptionBadge": true
  },
  "scrapedAt": "2026-08-05T21:40:12.884Z"
}
```

### Input

| Field | Type | Default | What it does |
| --- | --- | --- | --- |
| `profiles` | array of text | — | **Required.** The accounts to collect from. An account name, an `@name` or a link to the profile all work. |
| `maxPostsPerProfile` | integer | `100` | How many posts to take from each account, newest first. |
| `postedAfter` | text | — | Keep only posts published on or after this date (`YYYY-MM-DD`). |
| `postedBefore` | text | — | Keep only posts published on or before this date (`YYYY-MM-DD`). |
| `minLikes` | integer | `0` | Skip posts below this like count. |
| `minViews` | integer | `0` | Skip posts below this view count. |
| `includeReposts` | boolean | `true` | Keep posts the account reposted. The original is included alongside. |
| `includeReplies` | boolean | `true` | Keep posts that are replies. |
| `onlyWithMedia` | boolean | `false` | Keep only posts with an image, video or GIF. |
| `onlyWithLinks` | boolean | `false` | Keep only posts that link out. |
| `languages` | array of text | all | Keep only these languages, as two-letter codes such as `en`, `es`. |
| `includeAuthorProfile` | boolean | `true` | Attach the account's follower count and badges to every row. |
| `accountsAtOnce` | integer | `3` | How many accounts to work through at once. |
| `countryCode` | select | `us` | Which country to browse from. |

### Output fields

| Field | Description |
| --- | --- |
| `postId`, `url` | Identifier and permanent link. |
| `text` | Full post text. Long posts arrive complete, not cut off. |
| `createdAt` | Publication time, ISO-8601 UTC. |
| `language` | Language X detected for the post. |
| `likes`, `reposts`, `replies`, `quotes`, `bookmarks` | Engagement at collection time. |
| `views` | How many times X says the post was seen. |
| `isRepost`, `isReply`, `isQuote`, `isPinned` | Post type flags. |
| `repostOf`, `quotedPost` | The original post, when this one repeats or quotes another. |
| `author` | The account that wrote the post. |
| `profile` | Follower and post counts for the account you asked about. |
| `media` | Images, video files and GIFs, at the best quality available. |
| `hashtags`, `cashtags`, `mentions`, `links` | Entities found in the post. Links are the real destinations, not shortened. |
| `postedVia` | The app the post was published from. |
| `isLongForm`, `wasEdited`, `possiblySensitive`, `communityNote` | Extra context where X publishes it. |
| `unavailable`, `unavailableReason` | Set when an account cannot be collected, so your list keeps its shape. |

### Pricing

This actor is **pay per result**. You are charged for each post that lands in
your dataset, and for nothing else — no charge for accounts that turn out to be
empty, private or missing, and no time-based charge.

A run over 20 accounts at 100 posts each produces about 2,000 rows. Filters are
applied before anything is charged, so a run restricted to posts above 10,000
views only bills for the posts that clear the bar.

### Limits & what this actor cannot do

- X publishes a limited window of recent public posts per account, so very large
  accounts return what X makes available rather than a complete history.
- Keyword search across all of X is not part of what X publishes openly. This
  actor works from the accounts you supply rather than a search term.
- Replies written by *other people* underneath a post are not publicly
  available, and neither are the lists of who follows an account. Follower and
  following counts are included.
- Protected (private) accounts are not publicly viewable. They are reported as
  unavailable rather than returned empty, so your input list keeps its shape.
- Deleted and suspended posts are reported as unavailable rather than silently
  skipped.
- Likes, reposts, replies, bookmarks and views are a snapshot at the moment of
  collection and keep changing afterwards.
- X publishes view counts for most recent posts but not for every older one.
  Where X publishes none, `views` is left empty rather than set to zero. Setting
  a minimum view count therefore also excludes posts with no published count.
- Speed depends on the size of the job and on X's own response times.
- X's terms govern automated access. You are responsible for using the data
  lawfully, in line with the source site's terms, and for handling any personal
  data in line with applicable privacy law.

### FAQ

**Do I need an X account?**
No. Nothing is required from you beyond the list of accounts you want.

**Does it need my login, password or a paid X subscription?**
No. None of those are used at any point.

**Can I schedule it?**
Yes. Schedule it on Apify to run hourly, daily or weekly and keep collecting new
posts as they appear.

**Can I get every post an account ever wrote?**
Not always. X publishes a limited window of recent posts per account. For most
accounts that is a deep archive; for very high-volume accounts it stops short of
the beginning.

**Why is `views` empty on some older posts?**
Because X does not publish a view count for them. The field is left empty rather
than filled with a zero that would be wrong.

**How do I get the results into my tools?**
Export from Apify as CSV, Excel, JSON, XML or an HTML table, push into Google
Sheets, or pull them programmatically into your own system.

# Actor input Schema

## `profiles` (type: `array`):

The accounts to collect posts from. Paste an account name, an @name, or a link to the profile — all three work.

## `maxPostsPerProfile` (type: `integer`):

How many posts to collect from each account, newest first. X publishes only a limited recent window per account, so a high value returns everything X makes available rather than the account's full history — for some accounts that is a few hundred posts.

## `postedAfter` (type: `string`):

Only keep posts published on or after this date (YYYY-MM-DD). Leave empty for no lower bound.

## `postedBefore` (type: `string`):

Only keep posts published on or before this date (YYYY-MM-DD). Leave empty for no upper bound.

## `minLikes` (type: `integer`):

Skip posts with fewer likes than this.

## `minViews` (type: `integer`):

Skip posts with fewer views than this. Older posts that X publishes no view count for are skipped when this is set.

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

Keep posts the account reposted from someone else. The original post is included alongside.

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

Keep posts that are replies to another post.

## `onlyWithMedia` (type: `boolean`):

Keep only posts that carry at least one image, video or GIF.

## `onlyWithLinks` (type: `boolean`):

Keep only posts that link out to another site.

## `languages` (type: `array`):

Keep only posts in these languages, as two-letter codes such as en, es, fr. Leave empty for all languages.

## `includeAuthorProfile` (type: `boolean`):

Add the account's follower count, name and badge status to each row, so the dataset works on its own without a second lookup.

## `accountsAtOnce` (type: `integer`):

How many accounts to work through in parallel. Raise it for large lists.

## `countryCode` (type: `string`):

The country to browse from. Affects which posts X shows publicly in a few regions.

## Actor input object example

```json
{
  "profiles": [
    "nasa"
  ],
  "maxPostsPerProfile": 100,
  "postedAfter": "2026-01-01",
  "postedBefore": "2026-12-31",
  "minLikes": 0,
  "minViews": 0,
  "includeReposts": true,
  "includeReplies": true,
  "onlyWithMedia": false,
  "onlyWithLinks": false,
  "languages": [],
  "includeAuthorProfile": true,
  "accountsAtOnce": 3,
  "countryCode": "us"
}
```

# 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 = {
    "profiles": [
        "nasa",
        "@elonmusk",
        "https://x.com/OpenAI"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("guezi/x-profile-posts-scraper").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 = { "profiles": [
        "nasa",
        "@elonmusk",
        "https://x.com/OpenAI",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("guezi/x-profile-posts-scraper").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 '{
  "profiles": [
    "nasa",
    "@elonmusk",
    "https://x.com/OpenAI"
  ]
}' |
apify call guezi/x-profile-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,guezi/x-profile-posts-scraper"
        }
    }
}

```

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/XrFPlBlo7SpWR9SOe/builds/e4p5B7o13r7OEgmgK/openapi.json
