# X Trends Scraper — 24 Hour Timeline (`smolevich90/x-trends-24h-timeline`) Actor

See what WAS trending on X (Twitter), not just what is: 24 hours of hourly snapshots with rank dynamics for 400+ locations, plus weekly, monthly and yearly leaderboards.

- **URL**: https://apify.com/smolevich90/x-trends-24h-timeline.md
- **Developed by:** [Stanislav Shupilkin](https://apify.com/smolevich90) (community)
- **Categories:** Social media, Marketing
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 1,000 trend rows

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/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

## X Trends Scraper — 24 Hour Timeline

See what **was** trending on X (Twitter), not just what is. Every other trends scraper hands you a single snapshot: fifty topics as of the second you pressed Run. By the time you notice something interesting, the moment it broke out is already gone.

This Actor returns the **whole last 24 hours, hour by hour** — roughly 22 hourly snapshots × 50 trends per location — plus a rank-dynamics row for every topic that tells you when it entered the chart, how high it climbed and whether it is still climbing. On top of that it can pull the aggregated leaderboards of the day, week, month and year.

No X account, no API keys, no browser, no cookies. Location slugs in, timeline out.

### What you can do with a trend timeline

- **Catch the breakout, not the aftermath.** A `drift` row marked `breaking` is a topic that entered the chart in the last few hours and is still going up. That is the window in which a post, a bid or a news desk can still act.
- **Measure how long a topic actually lasted.** `first_seen`, `last_seen` and `snapshots` turn "it was trending" into "it held the top 10 for six hours and died at 3am".
- **Rebuild the day for a market you were asleep for.** One run at 9am gives you the overnight timeline for Japan, Turkey or Brazil, in order, with ranks.
- **Compare locations on the same clock.** Run several locations in one go and see which topic crossed from one country's chart into another, and how many hours later.
- **Feed trend history to a model.** Every row is flat JSON with a timestamp and a rank — no scraping, no parsing, no pagination to write.
- **Track the long tail.** Weekly, monthly and yearly leaderboards show what dominated a market over a period, ranked either by tweet score or by total time spent trending.

### Example output

Three row shapes share one dataset, told apart by `kind`.

**`snapshot`** — one trend at one point in time. This is the timeline itself:

```json
{
  "kind": "snapshot",
  "location": "worldwide",
  "woeid": 1,
  "captured_at": "2026-09-04T19:36:33+00:00",
  "rank": 1,
  "trend_name": "Isak",
  "tweet_volume": null,
  "search_url": "https://twitter.com/search?q=Isak",
  "source": "trends24"
}
```

**`drift`** — one row per topic, summarising its whole life inside the window:

```json
{
  "kind": "drift",
  "location": "worldwide",
  "trend_name": "Real Madrid",
  "status": "breaking",
  "first_seen": "2026-09-04T21:20:21+00:00",
  "last_seen": "2026-09-04T22:12:32+00:00",
  "best_rank": 1,
  "worst_rank": 1,
  "first_rank": 1,
  "last_rank": 1,
  "rank_change": 0,
  "snapshots": 2,
  "rank_series": [
    { "captured_at": "2026-09-04T21:20:21+00:00", "rank": 1 },
    { "captured_at": "2026-09-04T22:12:32+00:00", "rank": 1 }
  ],
  "source": "trends24"
}
```

**`top-period`** — one row of an aggregated leaderboard:

```json
{
  "kind": "top-period",
  "location": "united-states",
  "period": "week",
  "metric": "tweeted",
  "rank": 1,
  "trend_name": "#NationalDogDay",
  "score": 394,
  "score_label": "394",
  "last_seen": "2026-09-03T22:24:31+00:00",
  "last_seen_label": "1 day ago",
  "source": "getdaytrends"
}
```

Export as JSON, CSV, Excel or XML, or read it straight from the Apify API.

#### How to read `status`

| Status | Meaning |
|---|---|
| `breaking` | First appeared in the **second half** of your window and has not slipped since — a newcomer on the way up. |
| `sustained` | Still in the newest snapshot and holding near its own best rank. |
| `fading` | Gone from the newest snapshot, or still present but more than 10 places below its own peak. |

`status` answers "where is this topic in its life cycle", **not** "how hard did it move". A topic that has held the chart all day and climbed forty places stays `sustained` — it is not new. The size of the move is in `rank_change`, so sort or filter on that when you want movers rather than newcomers.

### How to run it

1. Put one or more locations into **Locations**: `worldwide`, `united-states`, `united-states/new-york`, `japan/tokyo`, a full `trends24.in` URL, or a numeric WOEID. 467 locations are available — Worldwide, 62 countries and 402 cities.
2. Under **What to collect**, `24h` (the hourly timeline) and `week` (the weekly leaderboard) are on by default; add `day`, `month` or `year` for the other aggregated leaderboards, or drop `week` if you only want the timeline.
3. Run it. Rows stream into the dataset as each location is parsed.

### Input options

| Field | What it does | Default |
|---|---|---|
| `locations` | Slugs, trends24 URLs or WOEIDs | `["worldwide"]` |
| `periods` | `24h` for the hourly timeline; `day` / `week` / `month` / `year` for leaderboards | `["24h", "week"]` |
| `windowHours` | How far back the timeline goes, counted from the newest snapshot (1–24) | 24 |
| `includeDrift` | Add the rank-dynamics row per topic | true |
| `liveOnly` | Skip the timeline, return only what is trending right now, straight from X | false |
| `maxTrendsPerSnapshot` | Keep only the head of each chart (1–50) — cuts the cost of a run proportionally | 50 |
| `metrics` | Leaderboards only: `tweeted` (tweet score) or `longest` (total time trending) | `["tweeted"]` |

### Pricing: pay per event

You are charged for rows, not for runtime:

| Event | Price |
|---|---|
| `trend-row` — one `snapshot` or `top-period` row | $0.0003 |
| `drift-summary` — one `drift` row | $0.003 |

A full 24-hour timeline for one location is about 22 snapshots × 50 trends = 1100 trend rows ($0.33) plus roughly 260 drift rows ($0.79) — around **$1.12 per location**. A weekly leaderboard is 30 rows, under a cent.

Cheaper ways to run it, in order of effect:

- `maxTrendsPerSnapshot: 10` — top 10 only, about $0.25 per location including drift.
- `includeDrift: false` — the timeline without the summaries, $0.33 per location.
- `windowHours: 6` — the last six hours instead of the whole day.
- `liveOnly: true` — one live snapshot, $0.015 per location.

If you set a maximum spend on the run, the Actor stops as soon as your limit is reached and finishes **successfully** with everything collected up to that point. You keep the partial dataset and pay nothing extra.

### Limits worth knowing before you run it

- **`tweet_volume` is almost always `null`.** X stopped publishing tweet counts for trends in January 2026. The field is kept because the sources still carry it for the rare topic that has one, but do not build on it. Use `rank`, `snapshots` and the leaderboard `score` instead.
- **`day` / `week` / `month` / `year` are aggregated leaderboards, not hourly history.** Hour-by-hour data only exists for the last 24 hours; nobody publishes it deeper than that for free. A `top-period` row tells you a topic was among the biggest of that week and gives it a score — it does not tell you which hours it occupied. Do not expect a month-long timeline: `24h` is the only period that produces a timeline at all.
- **Snapshots are roughly hourly, not exactly hourly.** The source captures every 40–60 minutes, so a 24-hour window usually holds 20–23 snapshots, and their timestamps are what actually happened, not a tidy grid. Duplicate captures seconds apart are collapsed so the dynamics are not invented.
- **The timeline source sits behind a bot check.** If it answers with a challenge instead of a page, the run does not fail: it falls back to X's own public endpoint, which gives **one live snapshot** instead of the 24-hour timeline. Every row carries a `source` field (`trends24` or `x-guest-api`), so a degraded run is obvious in the data rather than silent, and the run log says so explicitly. In that case there is no drift, because a single snapshot has no dynamics.
- **Leaderboards are per country.** Cities do not have their own leaderboard page, so a city location falls back to its country for `top-period` rows, and several cities of the same country are fetched once, not once each.
- **Drift needs at least two snapshots.** With `liveOnly`, or when only one snapshot is available, no `drift` rows are produced and nothing is charged for them.

# Actor input Schema

## `locations` (type: `array`):

Where to read trends from. Use a slug (worldwide, united-states, united-states/new-york, japan/tokyo), a trends24.in URL, or a numeric WOEID. 467 locations are available: Worldwide, 62 countries and 402 cities.

## `periods` (type: `array`):

24h = the full hour-by-hour timeline of the last day (this is the point of the Actor). day / week / month / year = aggregated leaderboards — the top trends of that period with a score, not an hourly history.

## `windowHours` (type: `integer`):

How far back the hourly timeline goes, counted from the newest snapshot. 24 keeps everything the source has.

## `includeDrift` (type: `boolean`):

One extra row per trend with its first and last appearance, best rank, the full rank series and a breaking / sustained / fading status.

## `liveOnly` (type: `boolean`):

Skip the timeline and return just the trends that are live right now, straight from X. Cheapest mode; no rank dynamics, because a single snapshot has none.

## `maxTrendsPerSnapshot` (type: `integer`):

Each snapshot holds up to 50 trends. Lower it to keep only the head of the chart and cut the cost of a run proportionally.

## `metrics` (type: `array`):

Only affects day / week / month / year leaderboards. tweeted = ranked by tweet score, longest = ranked by total time spent trending.

## Actor input object example

```json
{
  "locations": [
    "worldwide",
    "united-states"
  ],
  "periods": [
    "24h",
    "week"
  ],
  "windowHours": 24,
  "includeDrift": true,
  "liveOnly": false,
  "maxTrendsPerSnapshot": 50,
  "metrics": [
    "tweeted"
  ]
}
```

# Actor output Schema

## `trends` (type: `string`):

Snapshot, drift and leaderboard rows for the requested locations and periods.

# 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 = {
    "locations": [
        "worldwide",
        "united-states"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("smolevich90/x-trends-24h-timeline").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 = { "locations": [
        "worldwide",
        "united-states",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("smolevich90/x-trends-24h-timeline").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 '{
  "locations": [
    "worldwide",
    "united-states"
  ]
}' |
apify call smolevich90/x-trends-24h-timeline --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,smolevich90/x-trends-24h-timeline"
        }
    }
}

```

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/lT9zIU1v8eKbcZbFq/builds/IBWfusZn1FuSaWYMc/openapi.json
