Twitter (X) Media Downloader
Download videos, photos, GIFs, audio and poster images from public Twitter/X posts - no login, no cookies. Works with post links or usernames, supports every video quality, audio-only M4A/MP3, quoted-post media and public signed download links.
Input schema
Input fields, types, required flags, descriptions, defaults, and prefills come from the published definition. Prefill examples are distinct from defaults.
| Field | Type | Required | Description |
|---|---|---|---|
postUrls | array | optional | Paste links of posts to download media from. Accepts x.com and twitter.com links, i/web/status links, or bare post IDs. Optional if you provide usernames or profile links below. |
usernames | array | optional | Scan a profile's media posts and download their photos, videos and GIFs. Type handles with or without @, or paste full profile links. Optional if you provide post links above. |
maxPostsPerUser | integer | optional | How many of each profile's most recent media posts to look at. Posts without matching media or filtered-out posts are skipped. |
Show all input fields
| Field | Type | Required | Description |
|---|---|---|---|
postUrls | array | optional | Paste links of posts to download media from. Accepts x.com and twitter.com links, i/web/status links, or bare post IDs. Optional if you provide usernames or profile links below. |
usernames | array | optional | Scan a profile's media posts and download their photos, videos and GIFs. Type handles with or without @, or paste full profile links. Optional if you provide post links above. |
maxPostsPerUser | integer | optional | How many of each profile's most recent media posts to look at. Posts without matching media or filtered-out posts are skipped. |
maxItems | integer | optional | Hard cap on dataset rows for the whole run. The actor stops collecting and downloading once this many files are emitted. |
mediaTypes | array | optional | Choose which kinds of media to download. All types are selected by default. |
imageQuality | string | optional | Quality to use for photos (and video poster images). Original is the full-resolution file posted on X. |
videoQuality | string | optional | Preferred video resolution. The actor picks the closest available quality when the exact one is not offered. |
downloadAllQualities | boolean | optional | Emit and download one separate file for every progressive MP4 quality X offers (for example 1080p, 720p, 480p) instead of only the preferred one. Every quality gets its own row, filename and download link. |
includePosterImage | boolean | optional | Save the thumbnail/poster image of each video or GIF as an additional photo file. |
includeAltText | boolean | optional | Attach the alt text (image description) X stores for each photo or video thumbnail to the media row. |
audioOnly | boolean | optional | Download only the audio track of videos. Photos and GIFs are skipped. Files are extracted with ffmpeg and file saving is enabled automatically. |
audioFormat | string | optional | Format used when Audio only is on. |
includeQuotedMedia | boolean | optional | Also download the photos, videos and GIFs that appear inside a quoted post (a post embedded in the linked post). Those rows are marked with mediaSource "quoted post". |
includeMetadata | boolean | optional | Attach the post text, date, conversation and reply/quote flags, hashtags, mentions, links, like/repost/reply/quote/bookmark/view counts, author name, avatar, verification and follower count, and a derived engagement rate to every downloaded file. |
minLikes | integer | optional | When scanning usernames, skip posts with fewer likes than this. Posts whose like count is unknown are kept. Leave at 0 to keep every post. |
minRetweets | integer | optional | When scanning usernames, skip posts with fewer reposts than this. Posts whose repost count is unknown are kept. Leave at 0 to keep every post. |
onlyVerifiedAuthors | boolean | optional | When scanning usernames, skip posts whose author is not verified. Posts where verification is unknown are kept. |
saveToFile | boolean | optional | Download each file into this run's key-value store and add a public signed download link. Turn off to collect metadata and direct CDN links only. |
Download the published input schema
View complete JSON
{
"properties": {
"audioFormat": {
"default": "m4a",
"description": "Format used when Audio only is on.",
"editor": "select",
"enum": [
"m4a",
"mp3"
],
"enumTitles": [
"M4A (AAC, smaller, native)",
"MP3 (widest compatibility)"
],
"prefill": "m4a",
"title": "Audio file format",
"type": "string"
},
"audioOnly": {
"default": false,
"description": "Download only the audio track of videos. Photos and GIFs are skipped. Files are extracted with ffmpeg and file saving is enabled automatically.",
"prefill": false,
"title": "Audio only (extract sound from videos)",
"type": "boolean"
},
"downloadAllQualities": {
"default": false,
"description": "Emit and download one separate file for every progressive MP4 quality X offers (for example 1080p, 720p, 480p) instead of only the preferred one. Every quality gets its own row, filename and download link.",
"prefill": false,
"title": "Download every video quality",
"type": "boolean"
},
"imageQuality": {
"default": "orig",
"description": "Quality to use for photos (and video poster images). Original is the full-resolution file posted on X.",
"editor": "select",
"enum": [
"orig",
"large",
"medium",
"small"
],
"enumTitles": [
"Original (highest quality)",
"Large",
"Medium",
"Small (lightest)"
],
"prefill": "orig",
"title": "Photo quality",
"type": "string"
},
"includeAltText": {
"default": true,
"description": "Attach the alt text (image description) X stores for each photo or video thumbnail to the media row.",
"prefill": true,
"title": "Include image alt text",
"type": "boolean"
},
"includeMetadata": {
"default": true,
"description": "Attach the post text, date, conversation and reply/quote flags, hashtags, mentions, links, like/repost/reply/quote/bookmark/view counts, author name, avatar, verification and follower count, and a derived engagement rate to every downloaded file.",
"prefill": true,
"title": "Include post and author metadata",
"type": "boolean"
},
"includePosterImage": {
"default": true,
"description": "Save the thumbnail/poster image of each video or GIF as an additional photo file.",
"prefill": false,
"title": "Also save video poster images",
"type": "boolean"
},
"includeQuotedMedia": {
"default": true,
"description": "Also download the photos, videos and GIFs that appear inside a quoted post (a post embedded in the linked post). Those rows are marked with mediaSource \"quoted post\".",
"prefill": true,
"title": "Include media from quoted posts",
"type": "boolean"
},
"maxItems": {
"default": 100,
"description": "Hard cap on dataset rows for the whole run. The actor stops collecting and downloading once this many files are emitted.",
"maximum": 10000,
"minimum": 1,
"prefill": 1,
"title": "Maximum media files to collect",
"type": "integer"
},
"maxPostsPerUser": {
"default": 20,
"description": "How many of each profile's most recent media posts to look at. Posts without matching media or filtered-out posts are skipped.",
"maximum": 1000,
"minimum": 1,
"prefill": 1,
"title": "Maximum media posts to check per username",
"type": "integer"
},
"mediaTypes": {
"default": [
"video",
"photo",
"gif"
],
"description": "Choose which kinds of media to download. All types are selected by default.",
"editor": "select",
"items": {
"enum": [
"video",
"photo",
"gif"
],
"enumTitles": [
"Videos",
"Photos",
"GIFs"
],
"type": "string"
},
"prefill": [
"video",
"photo",
"gif"
],
"title": "Media types to download",
"type": "array"
},
"minLikes": {
"default": 0,
"description": "When scanning usernames, skip posts with fewer likes than this. Posts whose like count is unknown are kept. Leave at 0 to keep every post.",
"maximum": 1000000000,
"minimum": 0,
"prefill": 0,
"sectionCaption": "Profile filters",
"sectionDescription": "Optional filters applied while scanning usernames. Directly linked posts are always collected.",
"title": "Minimum likes (profile scans)",
"type": "integer"
},
"minRetweets": {
"default": 0,
"description": "When scanning usernames, skip posts with fewer reposts than this. Posts whose repost count is unknown are kept. Leave at 0 to keep every post.",
"maximum": 1000000000,
"minimum": 0,
"prefill": 0,
"title": "Minimum reposts (profile scans)",
"type": "integer"
},
"onlyVerifiedAuthors": {
"default": false,
"description": "When scanning usernames, skip posts whose author is not verified. Posts where verification is unknown are kept.",
"prefill": false,
"title": "Only verified authors (profile scans)",
"type": "boolean"
},
"postUrls": {
"description": "Paste links of posts to download media from. Accepts x.com and twitter.com links, i/web/status links, or bare post IDs. Optional if you provide usernames or profile links below.",
"editor": "stringList",
"example": [
"https://x.com/NASA/status/2107095768821576019",
"2107516524965794217"
],
"items": {
"type": "string"
},
"prefill": [
"https://x.com/NASA/status/2107095768821576019"
],
"title": "Post links or IDs",
"type": "array"
},
"saveToFile": {
"default": true,
"description": "Download each file into this run's key-value store and add a public signed download link. Turn off to collect metadata and direct CDN links only.",
"prefill": false,
"title": "Save files and return download links",
"type": "boolean"
},
"usernames": {
"description": "Scan a profile's media posts and download their photos, videos and GIFs. Type handles with or without @, or paste full profile links. Optional if you provide post links above.",
"editor": "stringList",
"example": [
"NASA",
"https://x.com/elonmusk"
],
"items": {
"type": "string"
},
"prefill": [],
"title": "Usernames or profile links to scan",
"type": "array"
},
"videoQuality": {
"default": "best",
"description": "Preferred video resolution. The actor picks the closest available quality when the exact one is not offered.",
"editor": "select",
"enum": [
"best",
"2160p",
"1080p",
"720p",
"480p",
"worst"
],
"enumTitles": [
"Best available",
"2160p (4K)",
"1080p (Full HD)",
"720p (HD)",
"480p (SD)",
"Worst (smallest file)"
],
"prefill": "best",
"title": "Video quality",
"type": "string"
}
},
"required": [],
"schemaVersion": 1,
"title": "Twitter (X) Media Downloader",
"type": "object"
}
Output schema
Published result links and storage locations. This schema is not an exhaustive contract for every field in a dataset record.
| Field | Type | Required | Description |
|---|---|---|---|
media | string | optional | One row per downloaded video, photo, GIF, audio track or poster image, with media metadata and a public download link. Status rows explain deleted, protected or media-less posts. |
files | string | optional | Key-value store holding the downloaded media files and their public links. |
Download the published output schema
View complete JSON
{
"actorOutputSchemaVersion": 1,
"properties": {
"files": {
"description": "Key-value store holding the downloaded media files and their public links.",
"template": "{{links.apiDefaultKeyValueStoreUrl}}/keys",
"title": "Stored files",
"type": "string"
},
"media": {
"description": "One row per downloaded video, photo, GIF, audio track or poster image, with media metadata and a public download link. Status rows explain deleted, protected or media-less posts.",
"template": "{{links.apiDefaultDatasetUrl}}/items",
"title": "Downloaded media",
"type": "string"
}
},
"title": "Twitter (X) Media Downloader Output",
"type": "object"
}
Dataset schema
Published dataset views and any declared field definitions. A view can select only a subset of the returned record fields.
Download the published dataset schema
View complete JSON
{
"actorSpecification": 1,
"description": "One row per downloaded file, plus status rows for failures.",
"fields": {
"properties": {
"altText": {
"description": "Image description X stores for the photo or video thumbnail.",
"title": "Alt text",
"type": "string"
},
"audioFormat": {
"description": "Audio container used when the audio-only option is on.",
"enum": [
"m4a",
"mp3"
],
"title": "Audio format",
"type": "string"
},
"collectedAt": {
"description": "UTC timestamp when the row was created.",
"example": "2026-10-06T18:53:49+00:00",
"title": "Data collected at",
"type": "string"
},
"downloadStatus": {
"description": "finished, failed or notDownloaded.",
"enum": [
"finished",
"failed",
"notDownloaded"
],
"title": "Download status",
"type": "string"
},
"downloadUrl": {
"description": "Public signed download link for the stored file.",
"example": "https://api.apify.com/v2/key-value-stores/STORE/records/file.mp4?signature=...",
"title": "Download URL",
"type": "string"
},
"durationSeconds": {
"description": "Video or GIF duration.",
"example": 13.3,
"title": "Duration (seconds)",
"type": "number"
},
"fileSizeBytes": {
"description": "Real size of the downloaded file.",
"example": 3178943,
"title": "File size (bytes)",
"type": "integer"
},
"filename": {
"description": "File name used in the key-value store.",
"example": "2107095768821576019_video_1.mp4",
"title": "File name",
"type": "string"
},
"height": {
"description": "Media height in pixels.",
"example": 1080,
"title": "Height",
"type": "integer"
},
"likeCount": {
"description": "Number of likes on the post.",
"title": "Likes",
"type": "integer"
},
"mediaSource": {
"description": "post for the post's own media, quoted post for media inside a quoted post, poster image for a video thumbnail.",
"enum": [
"post",
"quoted post",
"poster image"
],
"title": "Media source",
"type": "string"
},
"mediaType": {
"description": "video, photo or gif.",
"enum": [
"video",
"photo",
"gif"
],
"title": "Media type",
"type": "string"
},
"mediaUrl": {
"description": "Media URL with the selected photo quality applied (videos/GIFs use the chosen stream).",
"example": "https://pbs.twimg.com/media/ABC123?format=jpg&name=large",
"title": "Media URL",
"type": "string"
},
"mediaUrlOriginal": {
"description": "Untouched X CDN URL of the media, without the quality parameter.",
"example": "https://pbs.twimg.com/media/ABC123",
"title": "Original media URL",
"type": "string"
},
"message": {
"description": "Human-friendly status or failure message.",
"title": "Message",
"type": "string"
},
"posterImageUrl": {
"description": "Poster image URL on video/GIF rows when includePosterImage is on, with the selected photo quality applied.",
"title": "Poster image URL",
"type": "string"
},
"retweetCount": {
"description": "Number of reposts on the post.",
"title": "Reposts",
"type": "integer"
},
"status": {
"description": "Status code on status rows.",
"enum": [
"noInput",
"invalidLink",
"invalidUsername",
"notFound",
"rateLimited",
"error",
"noMatchingMedia",
"noRecords"
],
"title": "Status code",
"type": "string"
},
"thumbnailUrl": {
"description": "Preview/poster image URL for videos and GIFs.",
"title": "Thumbnail URL",
"type": "string"
},
"tweetId": {
"description": "Numeric ID of the post the media belongs to.",
"example": "2107095768821576019",
"title": "Post ID",
"type": "string"
},
"tweetText": {
"description": "Text of the post.",
"title": "Post text",
"type": "string"
},
"tweetUrl": {
"description": "Canonical URL of the post.",
"example": "https://x.com/i/status/2107095768821576019",
"title": "Post URL",
"type": "string"
},
"type": {
"description": "media file for a downloaded file, status for a run message.",
"enum": [
"media file",
"status"
],
"example": "media file",
"title": "Row type",
"type": "string"
},
"uploaderUsername": {
"description": "Handle of the account that posted the media.",
"example": "NASA",
"title": "Uploader",
"type": "string"
},
"username": {
"description": "Username related to a status row.",
"title": "Username",
"type": "string"
},
"viewCount": {
"description": "Number of views on the post.",
"title": "Views",
"type": "integer"
},
"width": {
"description": "Media width in pixels.",
"example": 1920,
"title": "Width",
"type": "integer"
}
},
"required": [
"type",
"collectedAt"
],
"type": "object"
},
"title": "Twitter (X) Media Downloader Output",
"views": {
"allRecords": {
"display": {
"component": "table",
"properties": {
"collectedAt": {
"format": "date",
"label": "Data collected at"
},
"downloadUrl": {
"format": "link",
"label": "Download Link"
},
"filename": {
"label": "File"
},
"mediaType": {
"label": "Type"
},
"message": {
"label": "Message"
},
"status": {
"label": "Status"
},
"tweetId": {
"label": "Post ID"
},
"tweetUrl": {
"format": "link",
"label": "Post URL"
},
"type": {
"label": "Row Type"
}
}
},
"title": "All records",
"transformation": {
"fields": [
"type",
"status",
"message",
"tweetUrl",
"tweetId",
"mediaType",
"filename",
"downloadUrl",
"collectedAt"
]
}
},
"mediaFiles": {
"description": "One row per downloaded video, photo or GIF.",
"display": {
"component": "table",
"properties": {
"altText": {
"label": "Alt Text"
},
"collectedAt": {
"format": "date",
"label": "Data collected at"
},
"contentType": {
"label": "Content type"
},
"downloadStatus": {
"label": "Status"
},
"downloadUrl": {
"format": "link",
"label": "Download Link"
},
"durationSeconds": {
"format": "number",
"label": "Duration (s)"
},
"fileSizeBytes": {
"format": "number",
"label": "Size (bytes)"
},
"filename": {
"label": "File"
},
"height": {
"format": "number",
"label": "Height"
},
"mediaId": {
"label": "Media ID"
},
"mediaType": {
"label": "Type"
},
"mediaUrl": {
"format": "link",
"label": "Media URL"
},
"mediaUrlOriginal": {
"format": "link",
"label": "Original Media URL"
},
"postedAt": {
"format": "date",
"label": "Posted at"
},
"posterImageUrl": {
"format": "image",
"label": "Poster Image"
},
"quoteCount": {
"format": "number",
"label": "Quotes"
},
"quotedTweetUrl": {
"format": "link",
"label": "Quoted post"
},
"tweetUrl": {
"format": "link",
"label": "Post URL"
},
"uploaderName": {
"label": "Uploader name"
},
"uploaderUsername": {
"label": "Uploader"
},
"uploaderVerified": {
"label": "Verified"
},
"width": {
"format": "number",
"label": "Width"
}
}
},
"title": "Downloaded media",
"transformation": {
"fields": [
"tweetUrl",
"uploaderUsername",
"mediaType",
"filename",
"fileSizeBytes",
"width",
"height",
"durationSeconds",
"mediaUrl",
"mediaUrlOriginal",
"posterImageUrl",
"altText",
"downloadUrl",
"downloadStatus",
"postedAt",
"contentType",
"mediaId",
"uploaderName",
"uploaderVerified",
"quoteCount",
"quotedTweetUrl",
"collectedAt"
]
}
}
}
}
Key-value schema
Published key-value store definitions, when provided by this build.
This definition is not present in the default published build. See the published README for available documentation.
Published README
Read the full published documentation
Twitter (X) Media Downloader
Collect public Twitter / X media without an account, cookies or a browser. Paste post links or ask for a profile's media posts and get the actual files back — videos in any available quality, photos, GIFs, audio-only tracks and video posters — each with a public download link.
What it does
- Post mode — one link or ID per post, including
x.com,twitter.com,mobile.twitter.com,/i/web/status/links,/status/<id>/video/1links and bare numeric IDs. - Profile mode — walks a profile's media posts page by page, not just the handful shown to logged-out visitors.
- Both modes in one run — results are de-duplicated across the two paths.
- Status rows — deleted, protected, media-less and rate-limited targets produce an honest status row instead of a silent empty run.
Services
| Service | What you get |
|---|---|
| Video download | Best, 2160p, 1080p, 720p, 480p or smallest MP4; every quality can be saved as separate files |
| Photo download | Original, large, medium or small image files |
| GIF download | The MP4 file X serves for animated GIFs |
| Audio extraction | M4A (AAC) or MP3 soundtrack of a video |
| Poster images | The video/GIF thumbnail as a separate photo file |
| Quoted-post media | Media inside a quoted post, marked mediaSource: "quoted post" |
| Author and post context | Text, date, engagement counts, author name/avatar/verification/followers, hashtags, mentions, links, reply/quote flags and quoted post IDs |
| Profile context | Profile ID, follower count and media count on rows found through a username |
| Profile filters | Minimum likes, minimum reposts and verified-authors-only |
How it works
The actor reads X's public post data and the FxTwitter mirror, combines the fields each source is best at, and falls back to the X status page and oEmbed when a post looks missing. Videos and GIFs use X's direct CDN; if a direct file cannot be fetched, yt-dlp is tried as a last resort. Files are streamed to disk, checked for a sane size, stored in the run's key-value store and linked with a signed public URL. No request uses your cookies, login or API key.
Input
| Field | Type | Default | Description |
|---|---|---|---|
postUrls |
array | – | Post links or bare post IDs (the prefill uses one NASA post) |
usernames |
array | – | Handles, @handles or profile links to scan |
maxPostsPerUser |
integer | 20 |
Media posts to check per profile (1–1000) |
maxItems |
integer | 100 |
Hard cap on media rows for the whole run (1–10000) |
mediaTypes |
array | ["video", "photo", "gif"] |
video, photo, gif |
imageQuality |
string | orig |
orig, large, medium, small |
videoQuality |
string | best |
best, 2160p, 1080p, 720p, 480p, worst |
downloadAllQualities |
boolean | false |
One row and file per available MP4 quality |
includePosterImage |
boolean | true |
Save each video/GIF poster as a photo |
includeAltText |
boolean | true |
Attach X's image description when present |
audioOnly |
boolean | false |
Save only the audio track of videos; photos and GIFs are skipped |
audioFormat |
string | m4a |
m4a or mp3 when audio-only is on |
includeQuotedMedia |
boolean | true |
Include media from a quoted post |
includeMetadata |
boolean | true |
Attach post, author and engagement context |
minLikes |
integer | 0 |
Profile scans only: skip posts below this like count |
minRetweets |
integer | 0 |
Profile scans only: skip posts below this repost count |
onlyVerifiedAuthors |
boolean | false |
Profile scans only: skip unverified authors |
saveToFile |
boolean | true |
Store files and return signed links; off means metadata and CDN links only |
At least one post link/ID or username is required. Directly linked posts are always collected; the three filters apply while scanning usernames.
Example: download two posts
{
"postUrls": [
"https://x.com/NASA/status/2107095768821576019",
"https://x.com/SheCodeAfrica/status/2107516524965794217"
],
"videoQuality": "1080p",
"maxItems": 10
}
Example: scan a profile's media
{
"usernames": ["NASA"],
"maxPostsPerUser": 50,
"maxItems": 100,
"mediaTypes": ["video", "photo"],
"minLikes": 100,
"onlyVerifiedAuthors": true
}
Example: audio-only MP3
{
"postUrls": ["https://x.com/NASA/status/2107095768821576019"],
"audioOnly": true,
"audioFormat": "mp3"
}
Output
Every dataset row has type: media file for a collectible file, or status for a run message.
| Group | Fields |
|---|---|
| Identity | tweetId, tweetUrl, postedAt, conversationId, inReplyToTweetId, isReply, isQuote, isRetweet, quotedTweetId, quotedTweetUrl |
| Media | mediaType, mediaUrl, mediaUrlOriginal, contentType, mediaId, mediaKey, thumbnailUrl, posterImageUrl, filename, fileSizeBytes, width, height, durationSeconds, focusRects, allowDownload |
| Download | downloadUrl, downloadStatus, message |
| Video quality | variantQuality, variantBitrate, availableQualities, qualityCount, isBestQuality |
| Audio | audioFormat |
| Author | uploaderUsername, uploaderName, uploaderVerified, uploaderAvatarUrl, uploaderFollowers |
| Post context | tweetText, likeCount, retweetCount, replyCount, quoteCount, bookmarkCount, viewCount, engagementRate, hashtags, mentions, urls |
| Source | mediaSource (post, quoted post or poster image) |
| Profile | profileId, profileFollowers, profileMediaCount |
| Run | collectedAt |
Empty fields are omitted. Status rows carry status (noInput, invalidLink, invalidUsername, notFound, rateLimited, error, noMatchingMedia, noRecords), a human-readable message, and the related tweetUrl, tweetId or username.
Example record
{
"type": "media file",
"tweetId": "2107095768821576019",
"tweetUrl": "https://x.com/i/status/2107095768821576019",
"postedAt": "2026-10-05T13:09:13+00:00",
"mediaType": "video",
"mediaUrl": "https://video.twimg.com/amplify_video/.../avc1/1920x1080/video.mp4?tag=16",
"contentType": "video/mp4",
"mediaId": "2107095744146460672",
"filename": "2107095768821576019_video_1_1080p.mp4",
"fileSizeBytes": 3178943,
"width": 1920,
"height": 1080,
"durationSeconds": 13.3,
"downloadUrl": "https://api.apify.com/v2/key-value-stores/{STORE_ID}/records/...?signature=...",
"downloadStatus": "finished",
"uploaderUsername": "NASA",
"uploaderName": "NASA",
"uploaderVerified": true,
"uploaderFollowers": 92310189,
"likeCount": 7476,
"retweetCount": 1125,
"quoteCount": 97,
"bookmarkCount": 332,
"viewCount": 2961506,
"variantQuality": "1080p",
"isBestQuality": true,
"mediaSource": "post",
"collectedAt": "2026-10-29T00:00:00+00:00"
}
Usage cost
You pay the actor's per-result price shown on its Apify page plus normal Apify platform usage. With saveToFile: false no media bytes are stored, so a metadata-only run is the cheapest option. Downloads add key-value store usage proportional to the real file sizes. Keep maxItems and maxPostsPerUser at the values you need — the actor stops as soon as maxItems is reached.
FAQ
Do I need an X account, cookies or an API key? No. Everything is read from public, logged-out sources.
Can I download from a private or protected account? No. Protected and deleted posts return a notFound status row; they are not silently skipped.
How far back does a profile scan go? The walk follows X's media timeline page by page until maxPostsPerUser, maxItems or the end of the timeline. Large profiles can be rate-limited; lower maxPostsPerUser and re-run later.
How are video qualities chosen? The closest available quality to your preference is used. Portrait videos are compared by their short side, so a 1080×1920 video counts as 1080p. With downloadAllQualities, every progressive MP4 becomes its own row and file.
What happens with quoted posts? Media inside a quoted post is included by default and marked mediaSource: "quoted post". Turn includeQuotedMedia off to keep only the linked post's own media.
Does audio-only work on GIFs? No. Animated GIFs have no audio track, so they are skipped in audio-only mode along with photos.
What if a post has no media? You get one noMatchingMedia status row explaining it, not an empty dataset.
Do download links expire? Signed key-value store links follow your Apify storage retention. Re-run the actor or copy the files to your own storage for permanent archiving.
How do the profile filters treat unknown counts? A post whose like/repost count or verification status is unknown is kept rather than excluded.
Can I still use my saved inputs from the previous version? Yes. Old input keys are mapped automatically in code, so saved tasks keep running.
Notes
- All timestamps are UTC ISO 8601.
- Engagement rate is derived from likes, reposts, replies and quotes divided by the author's follower count; it is omitted when the follower count is unknown.
- Media URLs are direct X CDN links and open without a Referer header.
- Download links are public signed links tied to the run's key-value store.
- Use the actor only for content you have the right to download.
Limitations
- Public posts only: deleted posts, protected accounts and login-gated content are not accessible.
- Profile scans cover the most recent media posts X exposes publicly, up to 1,000 posts per run; deeper history is not addressable and very large profiles can hit rate limits, so re-run later if a scan stops early.
- A single media file larger than 1 GB is rejected to keep memory bounded.
- Some media is marked by X as not downloadable; those rows report
downloadStatus: "notDownloaded"with an explanation. - Quote media depends on the quoted post still being public.
- X changes its public endpoints periodically; the actor keeps several fallbacks, but a run can still return
rateLimitedorerrorstatus rows during an outage.
Python quickstart
Use a schema-derived input and the Python standard library to start a run. An Apify account and token are required for execution.
Source build b2lfr5bXEkHVsmX4j. Documentation is regenerated from the default published build; private drafts are not included.