# Twitter (X) Space Scraper (`dataspryva/twitter-x-space-scraper`) Actor

Collect public X Spaces without login. Get the Space title, state, schedule, live and replay listener counts, host and participants, replay audio with a downloadable file, and an optional captions/AI transcript.

- **URL**: https://apify.com/dataspryva/twitter-x-space-scraper.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Social media, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Space Collector — Metadata, Hosts, Replay & Transcripts

Collect public X (Twitter) Spaces without an account, cookies or API keys. Start from Space links, IDs or announcement posts — or let the actor discover Spaces from a keyword, hashtag or host handle. Every run returns clean, omit-empty records for the Space, its people, its replay audio and, when requested, a timed transcript.

### Three ways to find Spaces

| Mode | Input | What happens |
|---|---|---|
| Exact Spaces | `spaceUrls` | Reads a Space link, a bare Space ID, or the post that announces a Space. The Space card is resolved automatically. |
| Keyword / hashtag | `searchQueries` | Reads recent public posts matching the query and resolves the Spaces they announce. |
| Host | `hostUsernames` | Reads a host's recent public posts (and their search results) and resolves the Spaces they announce. |

All three modes can run in one go. Discovered Spaces are capped by `maxSpaces`; pasted links and IDs are always collected. When several inputs resolve to the same Space (for example its link and its announcement post), it is collected once. `spaceState` can keep only live, scheduled, ended or any Spaces.

### What you get

Each run writes rows with a `type`:

| type | Meaning |
|---|---|
| `space` | One Space with metadata, counts, host and participants |
| `space participant` | One row per host, speaker or listener |
| `video transcript` | The transcript summary with timed segments |
| `space transcript segment` | One row per timed segment (optional) |
| `status` | An honest problem row (invalid link, deleted Space, rate limit, unavailable replay) |

#### Space row

- **Identity:** `id`, `url`, `title`, `state`, `contentType`
- **Times:** `createdAt`, `scheduledStart`, `startedAt`, `endedAt`, `durationSeconds`, `updatedAt`, `replayStartSeconds`
- **Audience:** `listenersLive`, `listenersReplay`, `replayAvailable`
- **People:** `creator` (full public profile), `hostId`, `hostUsername`, `hostName`, `participants[]`, `participantCounts`
- **Space settings:** `topics`, `topicIds`, `mentionedUserIds`, `isMuted`, `isLocked`, `isEmployeeOnly`, `disallowJoin`, `noIncognito`, `conversationControls`, `maxAdminCapacity`, `maxGuestSessions`, `narrowCastSpaceType`
- **Replay:** `replayAudioUrl`, `replayAudioFileUrl`, `replayAudioFileBytes`, `replayAudioContentType`, `replayAudioDurationSeconds`
- **Source:** `sourceTweetId`, `sourceTweetUrl` when you started from an announcement post
- `mediaKey`, `collectedAt`

#### Participant row

`spaceId`, `spaceUrl`, `spaceTitle`, `participantIndex`, `role`, `userId`, `username`, `name`, `bio`, `location`, `website`, `followers`, `following`, `postCount`, `profileImageUrl`, `bannerUrl`, `isBlueVerified`, `verified`, `verifiedType`, `periscopeUserId`, `isMutedByAdmin`, `isMutedByGuest`, `collectedAt`.

#### Transcript row

`spaceId`, `spaceUrl`, `title`, `language`, `transcriptionMethod` (`captions` or `ai`), `modelUsed`, `segmentCount`, `fullTranscript`, `segments[]` (`index`, `start`, `end`, `text`), `collectedAt`.

Empty fields are omitted at every depth. There are no `null` values in the dataset.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `spaceUrls` | array | – | Space links, Space IDs, or announcement post links |
| `searchQueries` | array | – | Keywords or hashtags for Space discovery |
| `hostUsernames` | array | – | Handles whose recent posts announce Spaces |
| `maxSpaces` | integer | `20` | Cap for discovered Spaces (1–200) |
| `spaceState` | string | `any` | `any`, `live`, `upcoming` or `ended` |
| `includeParticipants` | boolean | `true` | Participant list on the Space row + participant rows |
| `includeParticipantProfiles` | boolean | `true` | Enrich participant stubs with public profile details |
| `maxParticipantProfiles` | integer | `50` | Profile lookups per Space (0 = all) |
| `includeReplayAudio` | boolean | `false` | Replay HLS link + downloadable audio file |
| `includeTranscript` | boolean | `false` | Produce a transcript from captions or Whisper |
| `transcriptSegmentsAsRows` | boolean | `false` | Emit one row per transcript segment |
| `transcriptionMethod` | string | `auto` | `auto`, `captions` or `ai` |
| `whisperModel` | string | `base` | `tiny`, `base`, `small`, `medium` or `large-v3` |
| `proxyConfiguration` | object | – | Optional; automatic fallback is built in |

At least one of `spaceUrls`, `searchQueries` or `hostUsernames` is needed.

#### Examples

Metadata and participants:

```json
{
  "spaceUrls": ["https://x.com/i/spaces/1YpKkZgnrDXxj"],
  "includeParticipants": true
}
```

Discover by keyword, keep only ended Spaces:

```json
{
  "searchQueries": ["#Space", "NASA"],
  "spaceState": "ended",
  "maxSpaces": 10
}
```

Discover from hosts:

```json
{
  "hostUsernames": ["NASA", "@SpaceX"],
  "maxSpaces": 5
}
```

Replay audio with a transcript:

```json
{
  "spaceUrls": ["1YpKkZgnrDXxj"],
  "includeReplayAudio": true,
  "includeTranscript": true,
  "transcriptionMethod": "auto",
  "transcriptSegmentsAsRows": true
}
```

#### Example Space record

```json
{
  "type": "space",
  "id": "1YpKkZgnrDXxj",
  "url": "https://x.com/i/spaces/1YpKkZgnrDXxj",
  "title": "Meet NASA's New Mission Control Flight Directors #AskNASA",
  "state": "Ended",
  "createdAt": "2022-07-19T15:25:30+00:00",
  "startedAt": "2022-07-19T15:59:30+00:00",
  "endedAt": "2022-07-19T16:45:16+00:00",
  "durationSeconds": 2746.0,
  "listenersLive": 47951,
  "listenersReplay": 112570,
  "replayAvailable": true,
  "hostUsername": "NASA",
  "participantCounts": {"total": 10, "admin": 1, "speaker": 9},
  "topics": ["NASA", "Science", "Space"],
  "collectedAt": "2026-11-07T09:15:00+00:00"
}
```

### How discovery works

Spaces are discovered from public posts, not from a private search index. The actor reads recent matching posts through X's public guest surfaces and resolves each post's Space card. This keeps the actor cookieless. Consequences:

- Discovery looks at recent public posts, not the entire archive.
- A Space with no public announcement post cannot be discovered by keyword or host. Paste its link or ID instead.
- Guest search is the least reliable public surface; a query can return fewer posts at busy times. The actor retries and falls back to the host's own timeline.
- X's signed-in Space search and topic browser are not available to guest callers. They are deliberately not faked.

### FAQ

**Do I need an X account, cookies or an API key?** No. The actor is fully cookieless and reads only public Spaces, public posts and public profiles.

**Does it work with private or deleted Spaces?** No. They produce a clear `status` row.

**Why is replay audio sometimes unavailable?** Live Spaces have no replay yet, and some hosts disable replay. You get a `status` row explaining which case applies.

**How is the replay file produced?** The public replay stream is downloaded and combined into one playable audio file, then stored with a stable download link. Very large replays (above roughly 250 MB) may exceed the file cap — you still get the streaming replay link.

**How do transcripts work?** With `auto`, native captions are used when the replay has them; otherwise Whisper AI runs over the audio. Captions are fast. AI time grows with the Space length, and long Spaces are split into 10-minute chunks to bound memory.

**Which Whisper model should I use?** `base` is the best balance on the default 1 GB. Larger models need more actor memory. The actor downgrades safely instead of crashing, and reports the model it actually used in `modelUsed`.

**How many rows will a run produce?** A Space with participants and a full transcript can produce several hundred rows. Longer Spaces and larger participant lists produce more. Discovery is capped by `maxSpaces`; pasted Spaces are not capped.

**Can I schedule it?** Yes. Use `searchQueries` or `hostUsernames` with a schedule to pick up newly announced Spaces, or run it after a recurring show with the host's handle.

**Is this affiliated with X?** No. It is a third-party actor that reads publicly visible content.

### Limits

- Public Spaces only; private, deleted or unavailable Spaces return a `status` row.
- Keyword/hashtag/host discovery covers recent public posts, not the full archive.
- Signed-in Space search and the topic browser are not reachable without credentials and are not supported.
- Replay audio and transcripts require a finished Space with replay enabled.
- AI transcription is CPU-bound; on 1 GB the actor runs `tiny`/`base` and may downgrade a larger requested model.
- Participant profile enrichment stops at `maxParticipantProfiles` per Space.

### Integrations

Use Apify's built-in integrations to send Space summaries, participant lists or transcripts to Google Sheets, Airtable, Slack, a webhook or your own API.

# Actor input Schema

## `spaceUrls` (type: `array`):

Paste Space links such as https://x.com/i/spaces/1YpKkZgnrDXxj, bare Space IDs, or the post that announces a Space (the actor finds the Space from its card). x.com and twitter.com links both work.

## `searchQueries` (type: `array`):

Find public Spaces from posts that match a keyword or hashtag, for example AI, crypto or #Space. Each query reads recent matching posts and resolves the Spaces they announce.

## `hostUsernames` (type: `array`):

Find Spaces announced by specific X accounts. Paste handles with or without @, or a profile URL.

## `maxSpaces` (type: `integer`):

Upper limit for Spaces found through keywords and hosts. Spaces that you paste as links or IDs are always collected.

## `spaceState` (type: `string`):

Only keep Spaces in this state. Applies to links and discovery alike.

## `includeParticipants` (type: `boolean`):

Add the host, speakers and listeners to the Space row and emit one separate "space participant" row per person.

## `includeParticipantProfiles` (type: `boolean`):

Look up each participant's public profile (bio, followers, website, verification) instead of only the compact name shown in the Space. Adds one request per participant.

## `maxParticipantProfiles` (type: `integer`):

Cap on profile lookups per Space. 0 means every participant. Large Spaces with many listeners can be expensive.

## `includeReplayAudio` (type: `boolean`):

Add the HLS replay link and, when a file can be produced, store a downloadable audio file with its duration and size.

## `includeTranscript` (type: `boolean`):

Produce a spoken-word transcript. Captions are used when the replay has them; otherwise AI speech recognition runs (slower and memory-hungry).

## `transcriptSegmentsAsRows` (type: `boolean`):

In addition to the transcript summary row, emit one "space transcript segment" row per timed segment.

## `transcriptionMethod` (type: `string`):

How the transcript should be produced.

## `whisperModel` (type: `string`):

Whisper model for AI transcription. Larger models are more accurate but need more actor memory; on 1 GB the actor safely falls back to a smaller model.

## `proxyConfiguration` (type: `object`):

Optional. The actor works without a proxy and switches to Apify Proxy automatically if X blocks the direct connection.

## Actor input object example

```json
{
  "spaceUrls": [
    "https://x.com/i/spaces/1YpKkZgnrDXxj",
    "1YpKkZgnrDXxj",
    "https://x.com/i/status/2119157462183858414"
  ],
  "searchQueries": [
    "AI",
    "#Space"
  ],
  "hostUsernames": [
    "NASA",
    "https://x.com/elonmusk"
  ],
  "maxSpaces": 1,
  "spaceState": "any",
  "includeParticipants": true,
  "includeParticipantProfiles": false,
  "maxParticipantProfiles": 10,
  "includeReplayAudio": false,
  "includeTranscript": false,
  "transcriptSegmentsAsRows": false,
  "transcriptionMethod": "auto",
  "whisperModel": "base"
}
```

# Actor output Schema

## `spaces` (type: `string`):

Dataset with one Space row, one participant row per person, transcript rows and status rows.

## `keyValueStore` (type: `string`):

Downloadable replay audio files, stored when replay audio is requested.

# 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 = {
    "spaceUrls": [
        "https://x.com/i/spaces/1YpKkZgnrDXxj"
    ],
    "maxSpaces": 1,
    "spaceState": "any",
    "includeParticipants": true,
    "includeParticipantProfiles": false,
    "maxParticipantProfiles": 10,
    "includeReplayAudio": false,
    "includeTranscript": false,
    "transcriptSegmentsAsRows": false,
    "transcriptionMethod": "auto",
    "whisperModel": "base"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/twitter-x-space-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 = {
    "spaceUrls": ["https://x.com/i/spaces/1YpKkZgnrDXxj"],
    "maxSpaces": 1,
    "spaceState": "any",
    "includeParticipants": True,
    "includeParticipantProfiles": False,
    "maxParticipantProfiles": 10,
    "includeReplayAudio": False,
    "includeTranscript": False,
    "transcriptSegmentsAsRows": False,
    "transcriptionMethod": "auto",
    "whisperModel": "base",
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/twitter-x-space-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 '{
  "spaceUrls": [
    "https://x.com/i/spaces/1YpKkZgnrDXxj"
  ],
  "maxSpaces": 1,
  "spaceState": "any",
  "includeParticipants": true,
  "includeParticipantProfiles": false,
  "maxParticipantProfiles": 10,
  "includeReplayAudio": false,
  "includeTranscript": false,
  "transcriptSegmentsAsRows": false,
  "transcriptionMethod": "auto",
  "whisperModel": "base"
}' |
apify call dataspryva/twitter-x-space-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/twitter-x-space-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/zhRubyXu0We3FiDsl/builds/aib0amnLWbKcMPzJe/openapi.json
