# Reading X Posts

> Read tweets and threads from X (Twitter). Use when the user shares an x.com or twitter.com URL and wants to read a post or thread. Covers single-tweet extraction via oEmbed (no auth, instant) and full thread reading via Playwriter.

- Skill: `remorses/reading-x-posts` (Agent Skill)
- Install (CLI): `npx skillmds@latest add remorses/reading-x-posts`
- Raw SKILL.md: https://api.skillmd.com/api/skills/remorses/reading-x-posts/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: remorses (https://skillmd.com/u/remorses)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/remorses/reading-x-posts

---


# Reading X posts

Two methods depending on what you need.

## Single tweet (oEmbed, preferred for one post)

Twitter's oEmbed endpoint returns the full text as JSON. No auth, no JS rendering, no rate limits.

```bash
curl -s 'https://publish.twitter.com/oembed?url=https://x.com/USER/status/ID' | jq -r '.html' | sed 's/<[^>]*>//g'
```

Or use `WebFetch`:

```
https://publish.twitter.com/oembed?url=https://x.com/USER/status/ID
```

The response JSON has `html` (blockquote with full tweet text), `author_name`, and `author_url`.

Limitation: oEmbed only returns the single tweet you request. It cannot fetch replies or thread continuations. You would need to know every reply's status ID upfront.

## Full thread (Playwriter)

Use Playwriter when you need the full thread, replies, or any content beyond a single post. X is JS-heavy so `webfetch`/`curl` on the page itself returns an empty shell.

```bash
# 1. Create a session
playwriter session new

# 2. Navigate to the tweet
playwriter -s <ID> -e '
state.page = context.pages().find(p => p.url() === "about:blank") ?? await context.newPage();
await state.page.goto("https://x.com/USER/status/STATUSID", { waitUntil: "domcontentloaded" });
await waitForPageLoad({ page: state.page, timeout: 8000 });
'

# 3. Extract the full thread as markdown
playwriter -s <ID> -e '
const content = await getPageMarkdown({ page: state.page, showDiffSinceLastCall: false });
console.log(content);
'
```

`getPageMarkdown` uses Mozilla Readability (same as Firefox Reader View). It strips nav, sidebar, ads, and returns just the thread content. Much cleaner than querying individual `[data-testid="tweetText"]` elements.

## Decision rule

- **One tweet, just need the text** -> oEmbed. Instant, zero setup.
- **Full thread, replies, or visual context** -> Playwriter. Requires a session but gets everything.

Never use `webfetch` or `curl` directly on `x.com` page URLs. The HTML is an empty JS shell.

