# X (Twitter) Posts Search (`scraper_one/x-posts-search`) Actor

✨ Search for X (formerly Twitter) posts using keywords or hashtags. Retrieve post URLs, content, publication dates, author details, and engagement metrics. Ideal for monitoring brand mentions on X over time.

- **URL**: https://apify.com/scraper_one/x-posts-search.md
- **Developed by:** [Scraper One](https://apify.com/scraper_one) (community)
- **Categories:** Social media, Lead generation, Other
- **Features:** Limited permissions
- **Stats:** 3,103 total users, 470 monthly users, 100.0% runs succeeded, 23 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.20 / 1,000 result items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## X (Twitter) Posts Search

![Apify Actor](https://img.shields.io/badge/Apify-Actor-blue)

This **Apify Actor** searches for posts on **X (formerly Twitter)** based on keywords or hashtags. The results include
post URL, content, publication date,
author information, and engagement metrics.

It's a powerful tool for **monitoring** public conversations on X, tracking **brand mentions**, staying updated on
**trending topics**, and discovering
**high-engagement** posts in real time.
**Stay ahead** of potential reputation risks, detect viral content, and join relevant discussions 🚀

### Features

- 🔍 Search by **keywords or hashtags**
- 🕐 Filter by **time window** (e.g. posts from the last 7 days)
- 🧵 Choose between **top** or **latest** results
- 🎥 Retrieve **media** (images, videos, gifs) from posts
- 📊 Extract **engagement metrics** (likes, reposts, replies, quotes)

### Input Parameters

| Parameter         | Type     | Required | Description                                                                                                               |
|-------------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------|
| `query`           | `string` | ✅        | Keyword or hashtag to search posts for.                                                                                   |
| `resultsCount`    | `number` | ❌        | Maximum number of posts to extract.  If not set, only a few of the first posts will be returned.                          |
| `timeWindowHours` | `integer` | ❌        | Posts from the last n **hours**, counted back from the start of the run. Omit or set to `0` to disable. |
| `timeWindow`      | `integer` | ❌        | Posts from the last n **days** (24 hours each), counted back from the start of the run. Omit or set to `0` to disable. |
| `since`           | `string` | ❌        | Inclusive start: `YYYY-MM-DD` at midnight UTC, or ISO 8601 date/time. A missing timezone means UTC. |
| `until`           | `string` | ❌        | `YYYY-MM-DD` includes the entire UTC day. An ISO 8601 date/time is an exclusive upper bound; a missing timezone means UTC. |
| `searchType`      | `string` | ✅        | `"top"` (Most popular / relevant) or `"latest"` (newest first). The input form selects `"top"` by default. |

#### Dates and time windows

All date fields and time windows work with **Latest** and **Most popular / Top**. You can choose a fixed date range, posts from a start date onward, posts up to an end date, or a rolling window such as the last four hours. Top ranks matching posts by popularity/relevance; Latest lists matching posts newest first.

For the separate `since` and `until` fields:

- Use `YYYY-MM-DD` for whole **UTC days**. The start date is included, and the end date includes the entire day. Setting both fields to `2026-11-03` selects November 3 only.
- For exact hours, use ISO 8601. The start is included; the end time is excluded. For example, `12:00:00Z` to `13:00:00Z` includes 12:00 but excludes 13:00.
- A missing timezone means **UTC**: `2026-11-03T12:00:00` and `2026-11-03T12:00:00Z` are equivalent. An explicit offset is also accepted: `2026-11-03T13:00:00+01:00` identifies the same instant.
- You may leave either boundary empty. An invalid date is ignored individually, with a short warning in the run log; the other valid boundary still applies. If both dates are invalid, neither date restriction applies.
- If the end is earlier than the start (after accounting for the whole-day rule), `until` is ignored with a warning and `since` still applies.
- Posts have one-second timestamp precision. Equal start/end times select an empty range, while equal date-only fields select the entire UTC day.

#### Time filter priority

If more than one time filter is supplied, only the highest-priority source is used:

1. Date/time operators in `query`: `since:`, `until:`, `since_time:`, `until_time:` or `within_time:`.
2. A nonzero `timeWindowHours`.
3. A nonzero `timeWindow`.
4. The separate `since` and `until` fields, used together as one range.

For example, `timeWindowHours: 4` overrides `timeWindow: 7` and both separate date fields. If `query` already contains a date/time operator, all four date/window fields are ignored, even if the query supplies only one boundary. Operator names inside quoted search phrases, such as `"since:2026-11-03"`, are treated as search text.

Dates written directly in `query` retain X's date and timezone rules. They are independent of the UTC rules of the separate date fields.

**For existing users:** existing query formats and window fields remain supported. Two combinations now have different behavior: windows also apply to Top searches, and dates in `query` take priority over windows rather than being restricted by them. Saved inputs using these combinations may return different results.

#### Examples

Search without a time restriction:

```json
{
    "query": "SpaceX",
    "resultsCount": 30,
    "searchType": "top"
}
```

Get the newest matching posts from the last four days:

```json
{
    "query": "NASA",
    "resultsCount": 30,
    "timeWindow": 4,
    "searchType": "latest"
}
```

Get Top results from the last four hours:

```json
{
    "query": "bitcoin OR ethereum",
    "resultsCount": 30,
    "searchType": "top",
    "timeWindowHours": 4
}
```

Get Top results from one complete UTC day:

```json
{
    "query": "NASA",
    "resultsCount": 30,
    "searchType": "top",
    "since": "2026-11-03",
    "until": "2026-11-03"
}
```

Get posts from 12:00 UTC up to, but excluding, 13:00 UTC:

```json
{
    "query": "bitcoin",
    "resultsCount": 30,
    "searchType": "latest",
    "since": "2026-11-03T12:00:00Z",
    "until": "2026-11-03T13:00:00Z"
}
```

Timezone is optional; these times are also interpreted as UTC:

```json
{
    "query": "bitcoin",
    "searchType": "top",
    "since": "2026-11-03T12:00:00",
    "until": "2026-11-03T13:00:00"
}
```

If the end precedes the start, keep the start date and ignore the end with a warning:

```json
{
    "query": "NASA",
    "searchType": "latest",
    "since": "2026-11-05",
    "until": "2026-11-03"
}
```

Use the four-hour window; the seven-day window and separate dates are ignored:

```json
{
    "query": "bitcoin",
    "searchType": "top",
    "timeWindowHours": 4,
    "timeWindow": 7,
    "since": "2026-11-01",
    "until": "2026-11-03"
}
```

Keep a date-filtered query; `timeWindowHours` is ignored:

```json
{
    "query": "bitcoin since_time:1793664000 until_time:1793750400",
    "searchType": "latest",
    "timeWindowHours": 4
}
```

### Output Data

The actor returns an array of JSON objects representing individual X posts.

#### Example Output

```json
[
    {
        "postText": "#Iceland hospital\nAnd\nPolice hell !! See you soon on court 😉 https://t.co/axWj1bexPl",
        "postUrl": "https://x.com/Maj33Majewska/status/1905313916126736649",
        "timestamp": 1743097211000,
        "conversationId": "1905313916126736649",
        "postId": "1905313916126736649",
        "media": [
            {
                "mediaUrlHttps": "https://pbs.twimg.com/amplify_video_thumb/1905313794902966272/img/0HvmBic_wjBJQa3b.jpg",
                "type": "video",
                "id": "1905313794902966272"
            }
        ],
        "author": {
            "name": "Natalie",
            "screenName": "Maj33Majewska",
            "followersCount": 142,
            "favouritesCount": 300,
            "friendsCount": 171,
            "description": "Strict and intelligent person is curious about @SpaceX"
        },
        "replyCount": 3,
        "quoteCount": 4,
        "repostCount": 4,
        "favouriteCount": 11
    }
]
```

✅ Let us know if you'd like to include additional data fields or filters.

### Usage

1. **Create an Apify account** and open the actor page.
2. **Configure input parameters** in the Apify UI or via API.
3. **Run the actor** and monitor logs for progress.
4. **Download extracted posts** in JSON, CSV, or Excel format.

### Limitations & Notes

- Ensure your usage of X's data complies with their [Terms of Service](https://twitter.com/en/tos).
- Avoid excessive scraping to reduce the risk of IP blocking or rate limiting.
- Media content is linked directly from X and may expire or be removed.
- Free users can retrieve up to **100 posts per search query**.
- Free users are rate-limited to a certain number of actually processed search queries per day.
- For higher usage limits, upgrade to a [paid Apify plan](https://apify.com/pricing). **Contact us if you need custom limits!**

### Works Best With

For best results, use this actor together
with [X Post Replies Scraper](https://apify.com/scraper_one/x-post-replies-scraper).

First, search for posts (tweets) matching your criteria using **X Posts Search**, then pass the `postUrl` values from
selected results into **X Post Replies Scraper**'s `postUrls` input to extract replies and enrich your dataset. ✅

#### Best Use Case Flow

- 🔎 Run X Posts Search → Find relevant posts based on keywords or hashtags
- 📥 Feed `postUrl` values into X Post Replies Scraper's `postUrls` input → Get replies for each selected post
- 📊 Gain insights → Analyze engagement, sentiment, and conversation threads

This combination provides a powerful workflow for understanding discussions around specific topics on X. 🚀

### Other Recommended Scrapers

If you're working with multiple platforms or want additional data sources, check out these scrapers:

- 🐦 [X (Twitter) Posts Search](https://apify.com/scraper_one/x-posts-search) — Find posts/tweets based on keywords,
  hashtags, and more
- 🐦 [X Post Replies Scraper](https://apify.com/scraper_one/x-post-replies-scraper) — Scrap replies of multiple X (
  Twitter) posts
- 🐦 [X Profile Posts Scraper](https://apify.com/scraper_one/x-profile-posts-scraper) — Scrap posts of specific X (
  Twitter) profile
- 📘 [Facebook Posts Search](https://apify.com/scraper_one/facebook-posts-search) — Discover Facebook posts for a given
  topic or page
- 📘 [Facebook Comments Scraper](https://apify.com/scraper_one/facebook-comments-scraper) — Extract comments from public
  Facebook posts
- 📘 [Facebook Reactions Scraper](https://apify.com/scraper_one/facebook-reactions-scraper) — Scrap reactions from
  Facebook posts (like, sad, haha, angry etc.)
- 📘 [Facebook Posts Scraper](https://apify.com/scraper_one/facebook-posts-scraper) — Scrap posts from Facebook pages,
  groups etc.
- 🎬 [YouTube Search Scraper](https://apify.com/scraper_one/youtube-search-scraper) — Extract videos from search queries
- 🎬 [YouTube Comments Scraper](https://apify.com/scraper_one/youtube-comments-scraper) — Extract comments from posted
  videos
- 🎬 [YouTube Downloader](https://apify.com/scraper_one/yt-downloader) — Download youtube videos

### Support & Contact

📬 Need help or found a bug? Open an issue or contact us at **scraper1one@gmail.com**

# Actor input Schema

## `query` (type: `string`):

The search term to look for.

## `resultsCount` (type: `integer`):

Number of search results to retrieve. If not set, only a few of the first posts will be returned. Note: Free-plan users can retrieve up to 100 posts per search query.

## `timeWindow` (type: `integer`):

Get posts from the last n days in Latest or Most popular. Omit or use 0 to disable. Query date operators and Time Window Hours take priority. Overrides Since and Until.

## `timeWindowHours` (type: `integer`):

Get posts from the last n hours in Latest or Most popular. Omit or use 0 to disable. Query date operators take priority. Overrides Time Window, Since and Until.

## `since` (type: `string`):

Start date/time, included in the results. Examples: 2026-11-03 (from midnight UTC); 2026-11-03T12:00:00 (from noon UTC). Times without a timezone are interpreted as UTC.

## `until` (type: `string`):

End date/time. Examples: 2026-11-03 (include the whole day, through 23:59:59 UTC); 2026-11-03T12:00:00 (strictly before noon UTC). Times without a timezone are interpreted as UTC.

## `searchType` (type: `string`):

What kind of posts you'd like to search for.

## Actor input object example

```json
{
  "query": "Iceland",
  "resultsCount": 30,
  "searchType": "top"
}
```

# Actor output Schema

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

No description

# 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 = {
    "query": "Iceland",
    "resultsCount": 30,
    "searchType": "top"
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraper_one/x-posts-search").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 = {
    "query": "Iceland",
    "resultsCount": 30,
    "searchType": "top",
}

# Run the Actor and wait for it to finish
run = client.actor("scraper_one/x-posts-search").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 '{
  "query": "Iceland",
  "resultsCount": 30,
  "searchType": "top"
}' |
apify call scraper_one/x-posts-search --silent --output-dataset

```

## MCP server setup

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

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/rBaTEHzveTxZPraGv/builds/yCRlAMqLJ0BRYIni8/openapi.json
