{"id":26718539,"url":"https://github.com/fxembed/fxembed","last_synced_at":"2025-05-14T01:02:42.822Z","repository":{"id":45691128,"uuid":"513704529","full_name":"FxEmbed/FxEmbed","owner":"FxEmbed","description":"Fix X/Twitter and Bluesky embeds! Use multiple images, videos, polls, translations and more on Discord, Telegram and others","archived":false,"fork":false,"pushed_at":"2025-04-06T02:07:52.000Z","size":12503,"stargazers_count":3154,"open_issues_count":48,"forks_count":99,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-06T05:16:27.483Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://fxembed.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FxEmbed.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"dangeredwolf"}},"created_at":"2022-07-13T23:59:04.000Z","updated_at":"2025-04-06T02:07:57.000Z","dependencies_parsed_at":"2024-01-03T01:45:29.498Z","dependency_job_id":"c00ada5c-4fae-4bc3-bd95-663f57f84268","html_url":"https://github.com/FxEmbed/FxEmbed","commit_stats":null,"previous_names":["fixtweet/fxtwitter","fixtweet/fixtweet","fxembed/fxembed"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FxEmbed%2FFxEmbed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FxEmbed%2FFxEmbed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FxEmbed%2FFxEmbed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FxEmbed%2FFxEmbed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FxEmbed","download_url":"https://codeload.github.com/FxEmbed/FxEmbed/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248294134,"owners_count":21079788,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-27T17:05:58.193Z","updated_at":"2025-04-10T20:43:50.360Z","avatar_url":"https://github.com/FxEmbed.png","language":"TypeScript","funding_links":["https://github.com/sponsors/dangeredwolf"],"categories":[],"sub_categories":[],"readme":"# FxEmbed \u003cimg src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/logos/fxembed.svg\" height=\"24\"\u003e\n\n## Home of FxTwitter, FixupX, and FxBluesky\n\n### Embed videos, polls, quotes, translations, \u0026 more on Discord, Telegram, and others!\n\n![][icons]\n\n[![Crowdin][crowdinbadge]][crowdin]\n[![esbuild][buildbadge]][build]\n[![Tests][testsbadge]][tests]\n[![Status][statusbadge]][status]\n[![License][licensebadge]][license]\n\n\u003c!-- Links \u0026 Badges --\u003e\n\n[icons]: https://skillicons.dev/icons?i=typescript,workers\n[build]: https://github.com/FxEmbed/FxEmbed/actions/workflows/build.yml\n[buildbadge]: https://github.com/FxEmbed/FxEmbed/actions/workflows/build.yml/badge.svg\n[tests]: https://github.com/FxEmbed/FxEmbed/actions/workflows/tests.yml\n[testsbadge]: https://github.com/FxEmbed/FxEmbed/actions/workflows/tests.yml/badge.svg\n[license]: https://github.com/FxEmbed/FxEmbed/blob/main/LICENSE.md\n[licensebadge]: https://img.shields.io/github/license/FxEmbed/FxEmbed\n[status]: https://status.fxtwitter.com\n[statusbadge]: https://status.fxtwitter.com/api/badge/8/uptime/720?label=Uptime%2030d\n[crowdinbadge]: https://badges.crowdin.net/fxtwitter/localized.svg\n[crowdin]: https://crowdin.com/project/fxtwitter\n\n## Written in TypeScript as a Cloudflare Worker to scale, packed with more features and [best-in-class user privacy 🔒](#built-with-privacy-in-mind).\n\n### `twitter.com`: Add `fx` before your `twitter.com` link\n\n### `x.com`: Add `fixup` before your `x.com` link\n\n### `bsky.app`: Add `fx` before your `bsky.app` link\n\n## Embed Videos and GIFs\n\nVideos and GIFs just work, so whether you are sharing memes or cat videos, go crazy!\n\n\u003cimg width=\"477px\" src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/videos.png\"\u003e\n\nOn Discord, we can also automatically embed videos linked from some other platforms, like YouTube, so they can play without having to open a browser.\n\n## Embed Polls (X/Twitter)\n\nIf you want to share the results of a poll, you can do so by just linking the post using FxTwitter or FixupX. This works even if the poll is still ongoing!\n\n\u003cimg width=\"440px\" src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/poll.png\"\u003e\n\n## Embed Quotes \u0026 Media\n\nQuotes and their media can provide important context to a post, so they're automatically displayed. We'll even surface their media if there isn't already media embedded in the quote.\n\n\u003cimg width=\"478px\" src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/quote.png\"\u003e\n\n## Translate Posts (X/Twitter)\n\nYou can translate a post into any other supported language, with the original and translated text displayed as space allows.\n\nJust append a post with its 2-letter ISO language code. So for English, add `/en` at the end.\n\nBluesky support is planned in the future, but this currently depends on X/Twitter's Google Translate endpoint.\n\n\u003cimg src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/translate.png\"\u003e\n\n## Direct media links\n\nWant to link directly to a post's media _without_ the embed? You can easily do that!\n\n\u003cimg width=\"490px\" src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/directmedia.png\"\u003e\n\nThere are a few supported ways to do this:\n\n- Add `d.` before the domain (so, `d.fxtwitter.com`)\n- Add `.mp4` to the end of videos or `.jpg` to the end of images, after the post ID\n\nExamples from above:\n\n- `https://d.fxbsky.app/profile/wuff.gay/post/3lkordyy77k2a`\n- `https://fxtwitter.com/example/status/1548119328498728960.mp4`\n- `https://fixupx.com/example/status/1548117889437208581.jpg`\n\nPosts with multiple images are supported, so you can do something like this and it will pick the correct one:\n\n`https://d.fixupx.com/example/status/1547514042146865153/photo/3`\n\nOtherwise, it will default to the first image.\n\n## Combine multiple images into one\n\nBy default, FxEmbed will combine multiple images into one, allowing you to see all images on all platforms. You can also opt in to have images displayed using Discord's native multi-image so you can view individual, full-quality images (but, it doesn't work on iOS :( )\n\n- `https://m.fxtwitter.com/example/status/123456789123456789`\n- `https://m.fixupx.com/example/status/123456789123456789`\n- `https://m.fxbsky.app/profile/example.com/post/3lkord123abc`\n\n\u003cimg width=\"790px\" src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/mosaic.png\"\u003e\n\n## Gallery view\n\nUse `g.fxtwitter.com` or `g.fixupx.com` to generate minimal embeds with just the post's media and author information without other distractions. This can be particularly useful for read-only channels dedicated to sharing media.\n\n\u003cimg src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/gallery.png\"\u003e\n\n## Text-only view\n\nBasically the opposite of gallery view, use `t.fxtwitter.com` / `t.fixupx.com` to exclude photos/videos and only display text.\n\n\u003cimg src=\"https://raw.githubusercontent.com/FxEmbed/FxEmbed/main/assets/readme/textonly.png\"\u003e\n\n## Telegram Instant View\n\nView entire threads without leaving Telegram or opening a browser! You can unroll threads by just linking any part of the original thread. It will also keep track of any posts being replied to, up until the start of a conversation.\n\n\u003cimg width=\"515px\" src=\"https://github.com/FxEmbed/FxEmbed/blob/main/assets/readme/iv.png\"\u003e\n\n## Replace link shorteners with original link (X/Twitter)\n\nDefault X/Twitter embeds include t.co link shorteners, which make it difficult to know where the link is heading. We automatically replace t.co links with their original links to make things clearer.\n\n\u003cimg width=\"395px\" src=\"https://github.com/FxEmbed/FxEmbed/blob/main/assets/readme/tco.png\"\u003e\n\n## Redirect to Nitter or other custom instances (X/Twitter)\n\nIf you want to redirect to Nitter or another custom interface, you can set your custom redirect domain, like so: `https://fxtwitter.com/set_base_redirect?url=https://nitter.net`\n\nAt this time, the cookie is only set on the domain you set it on, so if you set it up using `fxtwitter.com`, `fixupx.com` will not redirect to your custom domain unless you set it there.\n\n## Built with privacy in mind\n\nFxEmbed doesn't save logs of what posts you're sending, nor do we have a public record of what posts are being embedded.\n\nIn fact, because our core embedding and API service uses Cloudflare Workers, FxEmbed can only run when you send it a request. Its memory doesn't stick around, and it doesn't have a file system or database to read from at all. That is how we keep our privacy promise by building it into the architecture. We use Cloudflare Analytics Engine to aggregate basic, anonymous statistics, which do not include information that could identify individual users or posts. My goal is always to provide a good public service, and FxEmbed doesn't have any ads or tracking to make money off of, nor do we sell data.\n\nTemporary real-time logging in the terminal (specifically `wrangler tail`) may be used only by the developer while the Worker is being serviced or debugged (to make sure things work as they should), however these logs are only shown in the terminal and are never saved or used for any other purpose. URLs that cause runtime errors in the script (aka Exceptions, usually exceedingly rare unless there was a faulty update pushed) may be logged for a developer to diagnose the issue that is preventing your embed from working.\n\nOn a different note, if the person who posted a FxTwitter or FixupX link forgot to strip tracking parameters (like `?s` and `\u0026t`), we strip it upon redirecting to the post as they are only used for telemetry and advertising.\n\n---\n\n## Why use FxEmbed?\n\nLet's compare using FxTwitter / FixupX since it's the most feature-complete. Here's a table comparing some of FxTwitter's features compared to Twitter default embeds as well as other embedding services\n\n|                                        |                  FxTwitter / FixupX                  |      Default       |                  vxTwitter (fixvx)                  |\n| -------------------------------------- | :--------------------------------------------------: | :----------------: | :-------------------------------------------------: |\n| Embed Posts / Image                    |                  :heavy_check_mark:                  | :heavy_check_mark: |                 :heavy_check_mark:                  |\n| Embed profile pictures on posts        |                  :heavy_check_mark:                  |        :x:         |         :ballot_box_with_check: If no media         |\n| Embed Videos                           |                  :heavy_check_mark:                  |        :x:         |                 :heavy_check_mark:                  |\n| Embed External Videos (YouTube, etc.)  |                 :heavy_check_mark:¹                  |        :x:         |                         :x:                         |\n| Embed Poll results                     |                  :heavy_check_mark:                  |        :x:         |                 :heavy_check_mark:                  |\n| Embed Quotes                           |                  :heavy_check_mark:                  |        :x:         |        :ballot_box_with_check: Without Media        |\n| Embed Multiple Images                  |                  :heavy_check_mark:                  |        :x:         |                 :heavy_check_mark:                  |\n| Translate Posts                        |                  :heavy_check_mark:                  |        :x:         |                         :x:                         |\n| Replace t.co with original links       |                  :heavy_check_mark:                  |        :x:         |                 :heavy_check_mark:                  |\n| Redirect to media file (without embed) |                  :heavy_check_mark:                  |        :x:         | :ballot_box_with_check: Subdomain broken, no images |\n| Gallery view                           |                  :heavy_check_mark:                  |        :x:         |                         :x:                         |\n| Strip tracking info on redirect        |                  :heavy_check_mark:                  |        :x:         |                 :heavy_check_mark:                  |\n| Show date / time of post               |  :heavy_minus_sign: Discord / Telegram Instant View  |        :x:         |                         :x:                         |\n| Show retweet, like, reply, view counts |  :heavy_minus_sign: Discord / Telegram Instant View  |        :x:         |     :ballot_box_with_check: No replies / views      |\n| Discord sed replace (`s/`) friendly    | :ballot_box_with_check: twittpr.com with twitter.com |        N/A         |                         :x:                         |\n| Telegram Instant View                  |                  :heavy_check_mark:                  |        :x:         |                         :x:                         |\n| Status fetch API for Developers        |                  :heavy_check_mark:                  |        N/A         |                 :heavy_check_mark:                  |\n| Last commit                            |                    [![][flc]][fc]                    |        N/A         |                   [![][vlc]][vc]                    |\n\n[flc]: https://img.shields.io/github/last-commit/FxEmbed/FxEmbed?label\n[vlc]: https://img.shields.io/github/last-commit/dylanpdx/BetterTwitFix?label\n[fc]: https://github.com/FxEmbed/FxEmbed/commits\n[vc]: https://github.com/dylanpdx/BetterTwitFix/commits\n\n¹ External media requiring web containers, such as YouTube, won't embed in Telegram because Telegram doesn't support it. Plain media will work in Telegram, and it works either way inside Discord.\n\n---\n\n## Why FxEmbed is nicer to develop for and deploy\n\nFxEmbed was designed for edge computing in mind, meaning it's easy to run closer to your users (which has significant latency advantages for people in many parts of the world). The way we use it and recommend deployment is using Cloudflare Workers, which are completely free for up to 100,000 requests per day, per account. Cloudflare Workers are [fast to set up](https://developers.cloudflare.com/workers/get-started/guide/) and your script is distributed in their datacenters around the world for lower latency. It may be possible to run it on other platforms that support Hono, but at this time we do not provide documentation to do so yet.\n\n## Deploy FxEmbed yourself\n\nℹ️ Currently, we only provide assistance with deploying with Cloudflare Workers, [but it may be possible to run on other web standards-compliant runtimes](https://hono.dev/getting-started/basic).\n\nClone the repo, install [Node.js](https://nodejs.org/) and run `npm install` in the repo directory. Copy `wrangler.example.toml` to `wrangler.toml` and add your [Cloudflare account ID](https://developers.cloudflare.com/fundamentals/get-started/basic-tasks/find-account-and-zone-ids/), and change the name of your worker if you need to. Also copy `.env.example` to `.env` and change any domains to your desired domain and whatever else you'd like to configure. You can configure branding by copying `branding.example.json` to `branding.json` and configuring it there. Authenticate with Cloudflare with `npx wrangler login`, then do `npm run deploy` (or `npx wrangler deploy --no-bundle`).\n\n[If you have more questions about setting up Cloudflare Workers, check out their Getting Started guide](https://developers.cloudflare.com/workers/get-started/guide/).\n\nOnce you're set up with your worker on `*.workers.dev`, [add your worker to your custom domain](https://developers.cloudflare.com/workers/platform/routing/custom-domains/).\n\nPopulate Sentry details in your `.env` to use Sentry in your product to catch exceptions.\n\n---\n\n## FAQ\n\n### What's the difference between `fxtwitter.com`, `twittpr.com`, and `fixupx.com`?\n\nThey all run the exact same worker and function identically... mostly.\n\n`fxtwitter.com` is the primary domain and `fixupx.com` exists to make it easy to fix `x.com` links as well (Very short .com domains are expensive, sorry I didn't get something shorter). Also, `twittpr.com` made it easy to do quick sed replacement on `twitter.com` links by sending the link and sending `s/e/p` afterward to automatically edit it, and you can still use that domain.\n\n### How come embedding takes so long / is not working in Telegram?\n\nTelegram's embedding servers sometimes never even send us a request to embed a URL, possibly due to their servers being overloaded. Try using [Webpage Bot](https://t.me/WebpageBot) to try to clear the cache of the embed.\n\n### What if I don't want to display all images in a given post?\n\nNo problem! You can pick any specific photo from a post using Twitter/X's own URL syntax (`/photo/1` is the first photo of a post) and we'll render you just that image. Bluesky has no such syntax for doing this, but we could implement something similar in the future.\n\n### Is FxEmbed associated with [some other website that starts with fx]?\n\nWe only operate on these domains:\n\n- `fxtwitter.com` / `twittpr.com`\n- `fixupx.com` (also `xfixup.com`)\n- `fxbsky.app`\n\n---\n\n**Licensed under the permissive MIT license. Feel free to send a pull request!**\n\n## Star History\n\n\u003ca href=\"https://star-history.com/#FxEmbed/FxEmbed\u0026Timeline\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=FxEmbed/FxEmbed\u0026type=Timeline\u0026theme=dark\" /\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=FxEmbed/FxEmbed\u0026type=Timeline\" /\u003e\n    \u003cimg alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=FxEmbed/FxEmbed\u0026type=Timeline\" /\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\n## Bugs or issues?\n\nFeel free to [open an issue](https://github.com/FxEmbed/FxEmbed/issues)\n\n## Additional Credits\n\n[Mosaic](https://github.com/FixTweet/mosaic) Multi-image combiner by [Antonio32A](https://github.com/Antonio32A) and improved by [Syfaro](https://github.com/Syfaro) and [Deer Spangle](https://github.com/Deer-Spangle)\n\n[Everyone else who has contributed to the main project!](https://github.com/FxEmbed/FxEmbed/graphs/contributors)\n\n## Disclaimer\n\nTwitter, Tweet, and X are trademarks of X Corp. This project is not affiliated in any way with X Corp or Twitter.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffxembed%2Ffxembed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffxembed%2Ffxembed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffxembed%2Ffxembed/lists"}