X Spaces API | Get Twitter Space Metadata and Speakers
Look up a single X Space by its id and get back its title, lifecycle state, host, topics, timing, audience counts and its admin, speaker and listener roster. Works for a Space that is scheduled, running or already ended. Billed at $0.0008 per call. Cost: $0.0008 per call.
GET spaces/info returns everything X exposes about one Space: title, state (Scheduled, Running or Ended), content type, the host profile, topics, the wrapper tweet, scheduled and actual start and end times, peak live listener count, replay view count, and the admin, speaker and listener rosters. It takes the Space id from a x.com/i/spaces/<id> URL and costs $0.0008 per call. Note that X does not retain the listener roster after a Space ends, so listeners is empty for an ended Space while the audience counts remain.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Query Parameters
The Space id, the trailing token in a x.com/i/spaces/ URL. 5-32 alphanumeric characters.
Include the listener roster. Defaults to true. X does not retain this roster after a Space ends, so it comes back empty for an ended Space regardless of this flag.
Include replay availability and related metadata. Defaults to true.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/spaces/info?id=1RKZzjkoYRAKB&with_listeners=true&with_replays=true"{ "space": { "id": "1RKZzjkoYRAKB", "title": "TIME TO BUILD!", "state": "Ended", "content_type": "visual_audio", "media_key": "28_2042268179733643265", "created_at": 1775749652198, "scheduled_start": 1775840400000, "started_at": 1775840398722, "ended_at": 1775842790853, "updated_at": 1775842791870, "total_live_listeners": 264, "total_replay_watched": 6290, "is_space_available_for_replay": true, "is_space_available_for_clipping": true, "is_locked": false, "is_muted": false, "is_employee_only": false, "no_incognito": false, "disallow_join": false, "is_subscribed": false, "max_admin_capacity": 3, "max_guest_sessions": 10, "narrow_cast_space_type": 0, "conversation_controls": 0, "topics": [ { "topic_id": "848920371311001600", "name": "Technology" }, { "topic_id": "857879302733418496", "name": "Entrepreneurship" } ], "creator": { "id": "825531272621654016", "username": "TheBestOfAdam", "name": "Adam Soccolich" }, "tweet": { "id": "2042648800989233184", "text": "https://t.co/TARX17sERY" }, "community_id": "1471580197908586507", "mentioned_user_ids": [ "1254214946751049729" ], "admins": [ { "user_id": "825531272621654016", "screen_name": "TheBestOfAdam", "display_name": "Adam Soccolich", "avatar_url": "https://pbs.twimg.com/profile_images/...", "periscope_user_id": "1WLERGNWdqRQb", "is_verified": true, "is_muted_by_admin": false, "is_muted_by_guest": false, "community_role": "Moderator", "start": 1775840398860 } ], "speakers": [], "listeners": [] }}{ "error": "bad_request", "message": "Missing or malformed parameter. Fix the request before retrying."}{ "error": "unauthorized", "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}{ "error": "insufficient_credits", "message": "Your balance is exhausted. Top up your credits to continue."}{ "error": "not_found", "message": "The resource does not exist, for example a deleted tweet or a private account."}{ "error": "rate_limited", "message": "Too many requests. Back off and retry with exponential backoff."}{ "error": "server_error", "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}Pricing
| Unit | Price |
|---|---|
| Per call | $0.0008 |
| Per 1,000 calls | $0.80 |
When to use
Use this when you have a Space id or URL and need its details: who hosted it, who spoke, what it was about, when it ran and how large the audience was. It is the read half of the Spaces surface. It does not return the audio itself.
Notes
- An ended Space returns an EMPTY listeners array even with with_listeners=true. X does not retain the per-person listener roster once a Space finishes; total_live_listeners and total_replay_watched still reflect the real audience. admins and speakers do survive.
- Timestamps are all millisecond-epoch numbers. X itself is inconsistent here, sending started_at as a number and ended_at as a string in the same payload; both are normalised to numbers so you can subtract them directly.
- 404 means the id resolved to no Space, which includes a Space the host deleted. 400 means the id was not a plausible Space id.
- This endpoint does not return the Space audio.
Related endpoints
- Tweet Detail: Fetch a single tweet's full object by ID.
- User Info by Username: Fetch a full profile by @handle.
- Trends: Read the current trending topics for a location.
FAQ
Where do I find a Space id?
It is the trailing token of the Space URL. In https://x.com/i/spaces/1RKZzjkoYRAKB the id is 1RKZzjkoYRAKB. A /peek suffix on the URL is not part of the id.
Why is the listeners array empty for a Space I know had an audience?
Because the Space has ended. X drops the per-person listener roster once a Space finishes and we pass through what X returns rather than inventing entries. The audience size is still available as total_live_listeners (peak concurrent while live) and total_replay_watched (replay views since).
Does this work for a Space that has not started yet?
Yes. A scheduled Space returns state Scheduled or NotStarted with scheduled_start set and started_at 0.
Can I get the audio recording of a Space?
Not from this endpoint, which returns metadata only.
Does it work for video Spaces?
Yes. A Space where the host enabled video comes back with content_type visual_audio; everything else about the response is the same.
Overview
Spaces: Read an X Space by id: title, host, speakers, topics, timing and audience counts, for a Space that is scheduled, running or already ended.
Overview
Grok: Ask X's own in-app Grok a question and get the answer back with the pages it cited. Grok reads X in real time, so it answers about posts and accounts a general model has never seen. Runs as your account, returns one buffered JSON document rather than a stream, and stores nothing: you pass prior turns back yourself.