# Twitter Screenshot Generator (`maximedupre/twitter-screenshot-generator`) Actor

Capture clean screenshots of public Twitter/X posts. Export dark, light, or paired theme images with tweet IDs, dimensions, visible metadata, and download URLs for API workflows.

- **URL**: https://apify.com/maximedupre/twitter-screenshot-generator.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Developer tools, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.95 / 1,000 twitter/x screenshots

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

### 📸 Twitter screenshot generator for public X posts

Twitter Screenshot Generator captures clean images of public [X/Twitter](https://x.com/) posts. Paste post URLs, mobile URLs, `@handle/status/id` paths, or raw status IDs, choose a dark, light, or paired theme, and get downloadable screenshot files plus a structured dataset with source IDs, image dimensions, visible tweet metadata, and scrape timestamps.

Use this Actor when you need repeatable tweet screenshots for reporting, research, social media monitoring, journalism notes, creator workflows, or internal archives. Instead of opening every post by hand and cropping screenshots one by one, you get consistent post images saved in Apify storage and linked from dataset rows you can export, schedule, or consume through the Apify API.

For a small first run, keep the prefilled public X post, leave **Theme** set to `Dark`, and start the Actor. Once the output looks right, paste your own list of public post links or status IDs.

### ✅ What this Actor does

- Captures clean screenshots of public Twitter/X posts.
- Accepts `x.com`, `twitter.com`, mobile Twitter URLs, `@handle/status/id` paths, and raw status IDs.
- Saves each screenshot as a PNG file in Apify key-value storage.
- Can also save a JPEG copy when **Image format** is set to `PNG and JPEG`.
- Supports dark screenshots, light screenshots, or both themes in one run.
- Emits one dataset item per successfully captured post and theme.
- Adds source fields such as original input, normalized URL, tweet ID, theme, screenshot key, download URL, image dimensions, file size, and capture time.
- Includes visible author handle, author name, and tweet text when those details are available on the rendered public post.
- Skips deleted, protected, unavailable, unsupported, or temporarily unreachable posts without saving failure rows.

The Actor is focused on known public post URLs and IDs. It does not discover posts from search, profiles, timelines, replies, followers, likes, repost users, or private accounts.

### 📦 Data you can export

Each output row represents one successfully captured screenshot. Core fields include:

- `input` and `originalUrl` - the value you submitted.
- `normalizedUrl` and `sourceUrl` - the normalized X post URL used for capture.
- `tweetId` - the public post ID.
- `theme` - `dark` or `light`.
- `status` - `success` for saved screenshot rows.
- `screenshotKey` and `screenshotUrl` - the PNG file in Apify storage.
- `scrapedAt` - UTC timestamp for the capture.
- `capturedElement` - `tweet`.
- `imageWidth`, `imageHeight`, and `sizeBytes`.
- `authorHandle`, `authorName`, and `visibleText` when visible on the post page.
- `jpegKey` and `jpegUrl` when JPEG export is enabled.

You can open the dataset in Apify, export it as JSON, CSV, Excel, XML, RSS, or HTML, call it through the Apify API, schedule repeat runs, or connect it to webhooks and integrations. Image files are stored separately and linked from each dataset row.

### 🚀 How to run

1. Add one or more public Twitter/X post targets in **Twitter/X posts**.
2. Use full URLs such as `https://x.com/_Sagiquarius_/status/2059744300075008499`, mobile URLs, `@handle/status/id` paths, or raw status IDs.
3. Keep **Screenshot limit** small for your first run.
4. Choose **Theme**: `Dark`, `Light`, or `Both`.
5. Choose **Image format**: `PNG` or `PNG and JPEG`.
6. Start the Actor and open the dataset.
7. Use each row's `screenshotUrl` to download the saved image.

Deleted posts, protected posts, unsupported targets, and posts that X does not make publicly available are skipped. The run continues with the remaining targets.

### 🧾 Input

#### 🎯 Targets

Enter one public post target per line.

```json
{
	"targets": [
		"https://x.com/_Sagiquarius_/status/2059744300075008499",
		"2059744300075008499",
		"@_Sagiquarius_/status/2059744300075008499"
	],
	"maxScreenshots": 25,
	"theme": "dark",
	"exportFormat": "png",
	"includeVisibleTweetMetadata": true
}
````

#### 🖼️ Screenshot options

`theme` controls how screenshots are rendered:

- `dark` - one dark-mode image per post.
- `light` - one light-mode image per post.
- `both` - one dark and one light image per post, counted as two screenshots.

`exportFormat` controls file output:

- `png` - save the PNG screenshot.
- `pngAndJpeg` - save PNG plus a JPEG copy.

`includeVisibleTweetMetadata` keeps visible author and text fields in the dataset. Turn it off only when you want the smallest possible row shape.

### 📄 Output example

```json
{
	"input": "https://x.com/_Sagiquarius_/status/2059744300075008499",
	"originalUrl": "https://x.com/_Sagiquarius_/status/2059744300075008499",
	"normalizedUrl": "https://x.com/i/status/2059744300075008499",
	"sourceUrl": "https://x.com/i/status/2059744300075008499",
	"tweetId": "2059744300075008499",
	"theme": "dark",
	"status": "success",
	"screenshotKey": "twitter-screenshot-2059744300075008499-dark-2026-05-28T10-54-25-307Z.png",
	"screenshotUrl": "https://api.apify.com/v2/key-value-stores/.../records/twitter-screenshot-2059744300075008499-dark-2026-05-28T10-54-25-307Z.png",
	"scrapedAt": "2026-05-27T17:44:16.471Z",
	"capturedElement": "tweet",
	"imageWidth": 598,
	"imageHeight": 607,
	"sizeBytes": 119509,
	"authorHandle": "@_Sagiquarius_",
	"authorName": "JStar",
	"visibleText": "OpenAI def needs to work on their orchestration. It’s ok/mid at best and often fails."
}
```

### 💳 Pricing

This Actor uses pay-per-event pricing. You are charged per successfully captured Twitter/X screenshot. If a target is deleted, protected, unsupported, or unavailable and no screenshot is saved, no screenshot row is emitted for that target.

When **Theme** is set to `Both`, each saved theme image counts as a separate screenshot. When **Image format** is set to `PNG and JPEG`, the JPEG copy is included with the same captured screenshot row.

### ⚠️ Limits and caveats

- Only public Twitter/X posts are supported.
- Protected, deleted, unavailable, login-only, or unsupported targets are skipped.
- The Actor does not require Twitter/X cookies, login details, or API keys.
- The Actor captures known post targets. It does not search X or crawl profiles.
- X may change how public posts render. If a public post fails to capture, rerun it once or file an issue with the post URL.
- Screenshots may include only the public content visible on the rendered post page.

### ❓ FAQ

#### 🔒 Can I screenshot private or protected tweets?

No. This Actor only captures public posts that X makes available without your credentials.

#### 🌓 Can I capture both dark and light screenshots?

Yes. Set **Theme** to `Both`. The Actor saves one dark and one light screenshot for each supported public post until it reaches your screenshot limit.

#### 🔢 Can I use raw tweet IDs instead of URLs?

Yes. You can paste raw status IDs such as `2059744300075008499`, full `x.com` or `twitter.com` URLs, mobile URLs, or `@handle/status/id` paths.

#### 💬 Does this Actor scrape replies, likes, or repost users?

No. It captures screenshots of known public post pages. Use a Twitter/X data scraper when you need search, timelines, replies, engagement rows, or profile discovery.

### 📝 Changelog

- 0.1: Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~twitter-screenshot-generator/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Other actors

- [Twitter Scraper ↗](https://apify.com/maximedupre/twitter-scraper) - Search public Twitter/X posts and export post data.
- [Social Media Stats Checker ↗](https://apify.com/maximedupre/social-media-stats-checker) - Check public profile stats across X and other social platforms.
- [TikTok Video Downloader ↗](https://apify.com/maximedupre/tiktok-video-downloader) - Download media files from known public TikTok video URLs.
- [TikTok Transcript Scraper ↗](https://apify.com/maximedupre/tiktok-transcript-scraper) - Extract transcripts and metadata from public TikTok videos.
- [LinkedIn Posts Scraper ↗](https://apify.com/maximedupre/linkedin-posts-scraper) - Export public LinkedIn post data from profiles, companies, and post URLs.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `targets` (type: `array`):

Enter one public X/Twitter post target per line. Full URLs, mobile URLs, @handle/status/id paths, and raw status IDs are accepted.

## `maxScreenshots` (type: `integer`):

Maximum number of screenshots to save across all targets and selected themes. If Theme is Both, each post can create two screenshots.

## `theme` (type: `string`):

Choose dark screenshots, light screenshots, or both themes for each public post.

## `exportFormat` (type: `string`):

Save each screenshot as PNG, or save PNG plus a JPEG copy for workflows that prefer smaller image files.

## `includeVisibleTweetMetadata` (type: `boolean`):

Include visible author handle, author name, and tweet text when those details are available on the public post page.

## Actor input object example

```json
{
  "targets": [
    "https://x.com/_Sagiquarius_/status/2059744300075008499"
  ],
  "maxScreenshots": 25,
  "theme": "dark",
  "exportFormat": "png",
  "includeVisibleTweetMetadata": true
}
```

# Actor output Schema

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

Open the dataset to view captured Twitter/X screenshot results.

# 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 = {
    "targets": [
        "https://x.com/_Sagiquarius_/status/2059744300075008499"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/twitter-screenshot-generator").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 = { "targets": ["https://x.com/_Sagiquarius_/status/2059744300075008499"] }

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/twitter-screenshot-generator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "targets": [
    "https://x.com/_Sagiquarius_/status/2059744300075008499"
  ]
}' |
apify call maximedupre/twitter-screenshot-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=maximedupre/twitter-screenshot-generator",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Twitter Screenshot Generator",
        "description": "Capture clean screenshots of public Twitter/X posts. Export dark, light, or paired theme images with tweet IDs, dimensions, visible metadata, and download URLs for API workflows.",
        "version": "0.1",
        "x-build-id": "hwi5myBeRP3bjgViT"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/maximedupre~twitter-screenshot-generator/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-maximedupre-twitter-screenshot-generator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/maximedupre~twitter-screenshot-generator/runs": {
            "post": {
                "operationId": "runs-sync-maximedupre-twitter-screenshot-generator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/maximedupre~twitter-screenshot-generator/run-sync": {
            "post": {
                "operationId": "run-sync-maximedupre-twitter-screenshot-generator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "targets"
                ],
                "properties": {
                    "targets": {
                        "title": "Twitter/X posts",
                        "minItems": 1,
                        "maxItems": 500,
                        "type": "array",
                        "description": "Enter one public X/Twitter post target per line. Full URLs, mobile URLs, @handle/status/id paths, and raw status IDs are accepted.",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "maxScreenshots": {
                        "title": "Screenshot limit",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Maximum number of screenshots to save across all targets and selected themes. If Theme is Both, each post can create two screenshots.",
                        "default": 25
                    },
                    "theme": {
                        "title": "Theme",
                        "enum": [
                            "dark",
                            "light",
                            "both"
                        ],
                        "type": "string",
                        "description": "Choose dark screenshots, light screenshots, or both themes for each public post.",
                        "default": "dark"
                    },
                    "exportFormat": {
                        "title": "Image format",
                        "enum": [
                            "png",
                            "pngAndJpeg"
                        ],
                        "type": "string",
                        "description": "Save each screenshot as PNG, or save PNG plus a JPEG copy for workflows that prefer smaller image files.",
                        "default": "png"
                    },
                    "includeVisibleTweetMetadata": {
                        "title": "Visible tweet metadata",
                        "type": "boolean",
                        "description": "Include visible author handle, author name, and tweet text when those details are available on the public post page.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
