English | 中文
x2markdown is a Chrome extension that converts visible webpage content into clean Markdown with one right-click — ready to paste into LLM chats, append to personal knowledge bases, or save as .md reference files. On x.com, it additionally provides dedicated export for posts and longform articles.
This project is primarily for showcase and personal use. It is open-sourced under the MIT license and does not accept external code contributions by default.
LLMs work best when they receive well-structured text. But getting content from a browser into that form is surprisingly manual:
- Dropping a link into an AI chat often fails to capture the full content or context.
- Copying visible webpage content loses structure — titles, links, body text, and image URLs all need manual cleanup.
- On
x.com, blogs, documentation sites, forums, and issue pages, there is frequently content that is "visible to me but unreadable by AI."
Whether you are pasting into a chat window, building an LLM-friendly knowledge base, or archiving web research as Markdown, x2markdown reduces the process to a single right-click.
- Adds "Copy as Markdown" to the right-click menu on any
http/httpspage. - For generic webpages:
- Copies the user's selection when one exists.
- Falls back to extracting the full page body when there is no selection.
- Shows a clear prompt to select content when the page is not recognized as an article.
- Copying a regular X post outputs:
- Author
- Time
- Link
- Body
- Quoted post (if present)
- Image links
- On
statusdetail pages, if the main post is followed by consecutive self-replies at the top, the extension exports the whole thread in order. - Copying an X Article or longform reading view additionally outputs the title.
- Generic webpage mode supports title, site name, author, time, body, and image links; missing fields are omitted.
- Images are output as links, not as embedded Markdown images.
- When a truncated post is hit in the timeline, it attempts to click "Show more" before copying.
- Runtime text follows the Chrome UI language, switching between Simplified Chinese and English.
- Success and failure toasts match the browser language.
- Supported detail page formats:
https://x.com/<user>/status/<id>https://x.com/<user>/article/<id>
- Supports right-click export of individual post cards visible in
x.comfeeds, lists, and search results.
- Does not export the full conversation page or other users' reply threads.
- Does not capture video, GIF, poll results, or comment sections.
- Does not attempt to bypass login walls, paywalls, or unrendered content.
- Does not cover
twitter.comormobile.x.com.
Install directly from the Chrome Web Store.
For local development or debugging:
- Clone the repository.
- Open Chrome and navigate to
chrome://extensions. - Enable "Developer mode" in the top right.
- Click "Load unpacked."
- Select the repository root directory.
- After making code changes, click "Reload" on the extension card.
- Open any webpage whose content you want to copy.
- To copy only part of the content, select the text first; to copy the entire article, right-click directly on the page.
- Choose "Copy Body as Markdown" or "Copy Selection as Markdown."
- Paste the result into an AI chat, Markdown editor, or note-taking tool.
Extra rules for x.com:
- On detail pages and longform pages, right-click anywhere to copy.
- On
statusdetail pages, it first tries to export the full thread defined as the main post plus the top consecutive self-replies. - In feeds, lists, and search results, right-click inside the target post card.
Regular post example:
Author: Example Author (@example)
Time: 2026-03-18 16:30:00
Link: https://x.com/example/status/1234567890123456789
Body:
This is an example post containing an [external link](https://example.com).
Quoted Post:
Author: Quoted Author (@quoted)
Time: 2024-01-02 12:55:59
Link: https://x.com/quoted/status/9876543210987654321
Body:
> This is the body of the quoted post.
Images:
- [Image 1](https://pbs.twimg.com/media/example-1.jpg?format=jpg&name=large)Generic webpage example:
# Understanding React Server Components
Site: react.dev
Author: React Team
Time: 2026-04-01 10:00:00
Link: https://react.dev/example
Body:
This is the extracted body content.
Images:
- [Image 1](https://example.com/hero.png)See docs/examples/post.md for X post, thread, and X Article output examples.
- Uses native Manifest V3.
- Uses Chrome's built-in
/_localesmechanism to providezh_CNandenruntime text; unmatched languages fall back to English. - Uses a
background service workerto create the Chrome right-click menu. - Permission strategy is kept minimal:
- Generic webpages rely only on
activeTab + scripting + contextMenus + clipboardWrite. - No site-wide
host_permissionsare declared. - Only
x.comretains a persistent content script for timeline card targeting.
- Generic webpages rely only on
- When the user clicks the menu item:
x.comroutes through the persistentcontent-x.js.- Other pages inject
shared.js + readability.js + content-generic.json demand.
- Generic mode prioritizes selection; only attempts Readability for full-page extraction when there is no selection.
- When a truncated X post is hit in the timeline, the content script clicks
tweet-text-show-more-linkinside the targetarticle[data-testid="tweet"]and waits for the text to expand before extracting. - On
statusdetail pages, it starts from the main post and collects only the top consecutive posts from the same author; it stops at the first visible reply from someone else. - X extraction logic relies primarily on visible DOM and semantic nodes:
article[data-testid="tweet"]time[datetime]data-testid="User-Name"data-testid="tweetText"data-testid="twitterArticleReadView"data-testid="twitter-article-title"
- Generic body extraction uses vendored
Mozilla Readability, then converts structured content via a local Markdown walker. - Clipboard write prefers
navigator.clipboard.writeText(), falling back todocument.execCommand('copy').
x2markdown/
├── AGENTS.md
├── LICENSE
├── README.md
├── README.zh-CN.md
├── background.js
├── content-generic.js
├── content-x.js
├── content.css
├── readability.js
├── shared.js
├── docs
│ ├── design.md
│ ├── examples
│ │ └── post.md
│ ├── images
│ │ └── overview.svg
│ └── troubleshooting.md
├── icons
│ ├── icon-16.png
│ ├── icon-32.png
│ ├── icon-48.png
│ ├── icon-128.png
│ └── logo.png
├── manifest.json
└── .gitignore
- X's DOM structure changes frequently; dedicated extraction logic may break.
- Generic webpage mode is biased toward "article pages" rather than aggregate pages; homepages, navigation pages, and product pages work better with selection mode.
- Full thread export on
statuspages only covers the main post plus the top consecutive self-replies, not the author's later scattered replies in the comment section. - Regular X posts have no native title, so no title field is output.
- Some longform articles render directly as a reading view on
statuspages and are exported in longform format. - Timeline posts rely on the most recently right-clicked visible card; if no post is hit, the extension reports failure.
- "Show more" depends on async rendering after a button click; if X does not return the full text, the extension extracts whatever is visible at that point.
- Only Simplified Chinese and English are built in; other browser languages fall back to English.
- Iframes, login walls, paywalls, and lazy-loaded unrendered content are not guaranteed to be exportable.
See docs/troubleshooting.md for common issues.
- License: MIT
- Repository purpose: showcase and reusable implementation reference
- Contribution policy: external PRs and issue workflow are not accepted by default
This project is licensed under the MIT License.