Skip to main content

Render tweets as PNG/JPG images using Playwright

Project description

tw2img

A tool that renders tweets as PNG images using Playwright (headless Chromium). Works with usernames, tweet IDs, URLs, local JSON files, or stdin. This style is based on nitter using Midnight theme as default.

image grid birdwatch note and thread

Installation

# Install required packages
pip install playwright
playwright install chromium

Quick Start

1. Guest Mode (no auth token required, missing context for replies)

# By @username (fetch latest tweet)
python tw2img.py @AP --guest
# By @username, fetch the 3rd most recent tweet
python tw2img.py @AP 3 --guest
# By tweet ID
python tw2img.py 2041557036274475228 --guest
# By tweet URL
python tw2img.py https://x.com/NASA/status/2041557036274475228 --guest

Here is a list of popular Twitter accounts sorted by most recent, and useful for guest access:
https://github.com/cmj/twitter-tools/wiki/RSS%E2%80%90Friendly

2. Authenticated Mode (full thread + reply data)

You need your Twitter auth tokens. Export them as environment variables:

export TWITTER_AUTH_TOKEN="your_auth_token_here"
export TWITTER_CSRF_TOKEN="your_ct0_token_here"
# alternative, only requires setting auth_token
export TWITTER_CSRF_TOKEN=$(openssl rand -hex 16)

Then run:

python tw2img.py 2054583770045386950

Where to find tokens: Open browser devtools, network tab, any x.com request, select cookies tab auth_token and ct0

Basic Options

Option Description
@user Fetch latest tweet from this user
--user <name> Same as above
--light Use light theme (default is dark)
--no-source Hide the "Twitter for iPhone" source text
--no-context Show only the focal tweet, no thread/replies
--no-retina Disable 2x retina rendering (smaller file)
--full-stats Show full numbers instead of abbreviated (e.g. 12,345 instead of 12.3K)
--output-dir <path> Directory to save output PNG (default: current working directory)
--width 800 Set output width in pixels (default: 598)
--css theme.css File to override the theme (ex: nitter/public/css/themes/pleroma.css)
--nitter Use Nitter default theme
--html-only Print HTML to stdout instead of rendering PNG
--save-html Save HTML to this file instead of rendering PNG
--imgur Upload PNG to imgur after rendering
--dump-json Print raw API JSON to stdout and exit
--view Automatically open the rendered output file after creation
--viewer <cmd> Specify custom viewer executable/command (e.g., viewnior, firefox, or kitty +icat {})
-c <file> Load config from a custom path (see Config below)

Config File

Options can be set as persistent defaults in a config file (INI format). Config is loaded in this order - later sources override earlier ones:

  1. ~/.config/tw2img/tw2img.conf - user default
  2. <script_dir>/tw2img.conf - next to the script, if present
  3. -c /path/to/custom.conf - explicit override
  4. Command options / flags always have highest priority

A default config is included as tw2img.conf. To install it:

mkdir -p ~/.config/tw2img
cp tw2img.conf ~/.config/tw2img/tw2img.conf

Set a default download directory in the config so you don't have to specify it each run:

[tw2img]
output_dir = ~/Pictures/tweets

If output_dir is set, all PNGs are saved there unless you pass an explicit output path (absolute or with a directory component) on the command line.

Use -c to load an alternate config for a specific run without touching your defaults:

python tw2img.py 2054583770045386950 -c ~/work/tw2img-work.conf --light

Input Types

# @username shorthand - latest tweet
python tw2img.py @NASA --guest

# @username shorthand - Nth most recent tweet (1-20, skips RTs and replies)
python tw2img.py @NASA 5 --guest

# Explicit --user flag (equivalent to @username)
python tw2img.py --user NASA --guest

# Tweet ID
python tw2img.py 2054583770045386950 --guest

# Full URL
python tw2img.py "https://x.com/username/status/123456789" --guest

# Local JSON file (from API)
python tw2img.py tweet.json

# Stdin (pipe JSON)
cat tweet.json | python tw2img.py -

Output

By default, saves as <screen_name>-<tweet_id>.png in current directory. Specify a custom filename as the argument after the input (or after the tweet index when using @username):

# Custom output with tweet ID
python tw2img.py 2054583770045386950 --guest my_screenshot.png

# Custom output with @username shorthand
python tw2img.py @NASA my_screenshot.png --guest

# Custom output with @username and tweet index
python tw2img.py @NASA 3 my_screenshot.png --guest

# Open with a specific GUI viewer
python tw2img.py @NASA --guest --view --viewer viewnior

# Render directly inline inside a supported terminal (like kitty)
python tw2img.py @NASA --guest --view --viewer "kitty +icat {}"

# View directly in Firefox (ideal when combined with --save-html)
python tw2img.py 2054583770045386950 --save-html tweet.html --view --viewer firefox

Examples

Basic screenshot with thread (dark mode):

python tw2img.py 2054583770045386950 --guest

Latest tweet from a user:

python tw2img.py @NASA --guest

5th most recent tweet from a user:

python tw2img.py @NASA 5 --guest

Automatically open the snapshot after rendering:

python tw2img.py @NASA --guest --view

Upload to imgur

python tw2img.py @NASA --guest --imgur

Light theme, focal tweet only:

python tw2img.py 2054583770045386950 --guest --light --no-context

Wide screenshot without source:

python tw2img.py 2054583770045386950 --guest --width 800 --no-source

Full stat numbers:

python tw2img.py 2054583770045386950 --guest --full-stats

Print HTML to stdout (for inspection or debugging)

python tw2img.py 2054583770045386950 --guest --html-only

Save HTML to a file

python tw2img.py 2054583770045386950 --guest --save-html tweet.html

Save HTML to a file and load in Firefox

python tw2img.py --guest @barackobama --full-stats --save-html /tmp/tweet.html && firefox /tmp/tweet.html

Articles

Save article and auto-load rendered HTML in Firefox

# BEST METHOD: Save as HTML and open (uses article_viewer from conf, or xdg-open)
# Use the tweet url that contains the article link (or simply just the id)
python article2img.py --guest --save-html out.html --view https://x.com/ARCRaidersGame/status/2054607629738037736
# Simplify with an alias
alias tw-article='article2img --guest --save-html /tmp/out.html --view > /dev/null'
tw-article https://n/XDevelopers/status/2041295840325636551

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tw2img-0.1.0.tar.gz (38.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tw2img-0.1.0-py3-none-any.whl (36.8 kB view details)

Uploaded Python 3

File details

Details for the file tw2img-0.1.0.tar.gz.

File metadata

  • Download URL: tw2img-0.1.0.tar.gz
  • Upload date:
  • Size: 38.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for tw2img-0.1.0.tar.gz
Algorithm Hash digest
SHA256 824ff330f5d6773d1ecb588f4805965ce386fa0e84a5e7d765cddb4f6efc7d72
MD5 6b09427e7c6d89d3c7dff1e8155ba9c9
BLAKE2b-256 f38bc4c0d8625a496f14a3f63569ca71089b6a41c296f5b7027312a09e628bab

See more details on using hashes here.

File details

Details for the file tw2img-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tw2img-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for tw2img-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 79ed7abd929e1700d59fac54bf1f9c5e4e85335a0773507b0e4aad052ac8ca14
MD5 ccba5ca96bf174da2020d7e5db3d285e
BLAKE2b-256 b4fe88fb49d05a508928543ab2e0f7179d382e8154e4dec36e2d9db1f0999621

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page