Why Your Image Link Won't Auto-Embed on PTT: 4 Different Rule Sets, Verified in Source Code
One link, four different outcomes — and it's not you
If you've never touched PTT, here's the thirty-second version: it's Taiwan's oldest and largest text-based BBS (bulletin board system), still running on a telnet-style terminal after more than two decades, with millions of active accounts. Anyone who spends time posting there eventually hits the same puzzle I did — paste an image link, and it sometimes turns into an inline thumbnail, sometimes just sits there as blue underlined text.
Most people's first instinct is that they messed up the URL format. They didn't. What actually trips people up isn't "which host is best" — it's that the same exact link can auto-expand into a thumbnail in the mobile app and then show up as a naked URL on the desktop web client, with nothing different on the poster's end.
That's not a fluke. "PTT" isn't one piece of software — it's at least four unrelated codebases, each deciding independently whether a URL should become an image. Some check the file extension. Some check a domain allowlist. Some demand both. And one host-matching approach is bold enough to skip extension checks entirely and just gamble that you pasted an Imgur link — more on that below.
In October 2025, there was a thread on PTT's ask board (the general Q&A board) asking which hosts support auto-embedding, where the original poster mentioned that hovering over an Imgur link on term.ptt.cc used to trigger an image preview — until it quietly stopped working about six months ago. That single sentence captures something most people never notice: the rules for the same client and the same host change over time, and nobody sends out a memo. So instead of trusting forum folklore, I went and pulled the source for the major clients myself. Every cell in the tables below traces back to an actual file.
PTT image viewing has 5 paths, not one "PTT" experience
Before the comparison gets confusing, let's separate the pieces.
- Plain-text BBS terminals (PCMan, Welly): text-only. Image links are always just a string of characters — never auto-rendered.
- www.ptt.cc web articles: when you load an article page in a browser, the server rewrites qualifying URLs into
<img>tags before it ever reaches you. - term.ptt.cc: a browser-based terminal emulator that connects over WebSocket. Hovering over a link pops up an image preview, driven entirely by client-side JavaScript.
- PttChrome: the long-running browser telnet client. Images get embedded directly into the post view.
- Mobile apps (Mo PTT, JPTT, PiTT, BePTT): these render links as inline thumbnails directly. They're closed-source, so this part of the picture comes from community reports, not code review.
The gap between the first two and the last three is bigger than it looks on paper.
I read the actual source — four rule sets, and none of them match
www.ptt.cc web articles: server-side, extension-first, no WebP
The web frontend for www.ptt.cc is called pttweb, and its source is public on GitHub under the ptt/pttweb repo. The file responsible for turning URLs into images is richcontent/url_based_finder.go, which holds an ordered list of patterns checked in sequence:
var defaultUrlPatterns = []*UrlPattern{
newUrlPattern(`^https?://(?:www\.youtube\.com/watch\?(?:.+&)*v=|youtu\.be/)([\w\-]+)`, handleYoutube),
newUrlPattern(`^https?://i\.imgur\.com/([\w]+)\.((?i)png|jpeg|jpg|gif)$`, handleImgurSingle),
newUrlPattern(`^http://picmoe\.net/d\.php\?id=(\d+)`, handlePicmoe),
newUrlPattern(`\.(?i:png|jpeg|jpg|gif)$`, handleGenericImage),
}
The last line is the one that matters. The first three are dedicated rules for YouTube, Imgur, and picmoe.net specifically. The fourth is the catch-all: any URL ending in .png, .jpeg, .jpg, or .gif (case-insensitive), from any host whatsoever, gets wrapped in an <img> tag automatically. In other words, www.ptt.cc web articles run on "extension matters, domain doesn't" — the exact opposite of term.ptt.cc's logic, as you'll see next.
There's a catch: the URL has to actually end at the extension, no query string allowed (the regex anchors on $). So a link like xxx.jpg?token=abc123 won't trigger the last rule at all. And .webp isn't in the list — meaning a perfectly valid WebP direct link will never auto-expand on www.ptt.cc web articles, full stop. That's a detail I haven't seen covered clearly elsewhere.
term.ptt.cc: domain allowlist comes first, extension is the second gate
term.ptt.cc's source lives at ptt/ptt-term on GitHub — a WebSocket-based web terminal for BBS. The module handling hover-to-preview is src/plugins/media_previewer/image_preview_util.js, and it hardcodes a default trusted-domain list:
export const INITIAL_TRUSTED_IMAGE_DOMAINS = [
"imgur.com", "imgtok.com", "meee.com.tw", "duk.tw",
"upload.cc", "ibb.co", "imgbb.com", "postimg.cc",
"twimg.com", "gyazo.com",
];
Notice what's missing: no urusai.cc, no vgy.me, no lpic.cc. Yet the same PTT ask-board thread had people swearing urusai.cc and vgy.me auto-embed fine for them. Contradiction? Not really — the code also ships a parseTrustedDomains function, meaning this list is user-configurable, and the default ten are just the out-of-the-box set, not the whole universe. My honest read is that person had already added urusai.cc to their own settings, not that term.ptt.cc ships site-wide support for it. That's an easy detail to mistake for a global rule.
The matching logic itself runs in two layers: Imgur gets a dedicated regex that works even without a file extension; anything under pbs.twimg.com/media/ skips the extension check entirely; and for everything else on the allowlist, the URL must end in .jpg, .jpeg, .png, .gif, .webp, or .bmp — and a query string is fine here, unlike the www.ptt.cc rule. So term.ptt.cc is an "AND" gate: domain and extension both have to check out.
PttChrome: domain-only, doesn't even bother checking extensions
PttChrome is older still. The maintained legacy version lives at iamchucky/PttChrome. The file rendering inline image previews is js/term_view.js, and it selects candidate links with this jQuery selector:
var aNodes = $(".main a[href^='http://ppt.cc/'], .main a[type='p'], " +
".main a[href^='http://imgur.com/'], .main a[href^='https://imgur.com/'], " +
".main a[href^='https://flic.kr/p/'], .main a[href^='https://www.flickr.com/photos/']")
.not("a[href^='http://imgur.com/a/'], a[href^='https://imgur.com/a/'], " +
"a[href^='http://imgur.com/gallery/'], a[href^='https://imgur.com/gallery/']");
Here's where it gets awkward. PttChrome checks zero file extensions — it only cares about URL prefixes, and the allowlist is just ppt.cc short links, imgur.com (excluding albums and gallery pages), flic.kr, and flickr.com/photos. urusai.cc, vgy.me, duk.tw, meee, ImgBB, Postimages, lpic.cc — none of them qualify, no matter how standard your direct link looks. It'll always just be a plain blue URL. And here's the part I find genuinely funny: for Imgur links, the code rewrites the URL to i.imgur.com/ID.jpg, hardcoding the .jpg extension regardless of whether the source image is actually a PNG or a GIF. It's a decade-plus-old quirk nobody notices in practice, because Imgur usually serves the correct image anyway even when the extension in the request doesn't match.
Mobile apps (Mo PTT, JPTT, PiTT): closed-source, community evidence only
I'll be upfront: I can't give you source-code-level answers here. Mo PTT, JPTT, and PiTT are all closed-source commercial apps with no public repos on GitHub. The strongest evidence I could find comes from two PTT ask-board threads posted close together, in June and October 2025, where users reported hands-on behavior: meee.com.tw links auto-embed once you manually add a .jpg extension; urusai.cc's i.urusai.cc/ID.png format works; imgpoi.com was flagged by multiple people as apparently having no auto-embed support at all. All of this points toward "extension-based" logic, closer to how www.ptt.cc's web version behaves — but nobody has produced source code or an official technical document confirming whether these apps also enforce a domain allowlist. I'm flagging this cell explicitly as unverified. I'm not going to pretend I reverse-engineered these apps when I didn't.
The 4 rule sets, side by side
| Client | What it checks | Extension requirement | WebP | Evidence level |
|---|---|---|---|---|
| www.ptt.cc web articles | Extension only, ignores domain | Must end in .jpg/.jpeg/.png/.gif, no query string allowed | Not supported | Source code (ptt/pttweb) |
| term.ptt.cc | Domain allowlist AND extension | Allowlisted domains need .jpg/.jpeg/.png/.gif/.webp/.bmp, query string OK | Supported | Source code (ptt/ptt-term) |
| PttChrome | Domain only, no extension check | Not checked (Imgur links get force-rewritten to .jpg) | N/A | Source code (iamchucky/PttChrome) |
| Mobile apps (Mo PTT/JPTT/PiTT) | Appears to be extension-based | Reportedly .jpg/.png/.gif work | Unverified | Community reports only, no source available |
Once you see the table laid out, the takeaway is obvious: there is no such thing as a single "universal PTT rule." The exact same host link can behave four different ways depending on which client someone opens it in.
For comparison, if you're used to Reddit or Discord, this will feel oddly familiar in reverse. Reddit's embed pipeline works off Open Graph metadata fetched server-side rather than a hardcoded domain list, and Discord's client checks the Content-Type header on the response instead of trusting the file extension in the URL at all — which is actually more robust than most of what's above, since it doesn't get fooled by a .jpg on a file that isn't one. PTT's ecosystem predates that approach by a long stretch, and each client just bolted on its own logic independently.
Host × client compatibility table
I built this by cross-referencing each rule set above against the direct-link format of the most commonly used hosts. ✅ means it should auto-expand per the rule logic, ❌ means it won't, ⚠️ means it depends on manual settings or extension tweaks.
| Host (direct link example) | www.ptt.cc web | term.ptt.cc (default) | PttChrome | App (community-reported) |
|---|---|---|---|---|
Imgur i.imgur.com/ID.jpg |
✅ | ✅ | ✅ (force-converted to .jpg) | ✅ |
meee meee.com.tw/ID.jpg |
✅ | ✅ | ❌ | ✅ (needs manual extension) |
| duk.tw | ✅ (with extension) | ✅ | ❌ | Unverified |
urusai.cc i.urusai.cc/ID.png |
✅ (with extension) | ⚠️ needs manual allowlist entry | ❌ | ✅ (community-reported) |
| vgy.me | ✅ (with extension) | ⚠️ needs manual allowlist entry | ❌ | Unverified, community calls it "the most finicky" |
ImgBB ibb.co / i.ibb.co |
✅ (with extension) | ✅ | ❌ | Unverified |
Postimages postimg.cc |
✅ (with extension) | ✅ | ❌ | Unverified |
lpic.cc lpic.cc/{code} |
❌ (no extension) | ❌ (not allowlisted, no extension) | ❌ | ❌ (no direct link available) |
Let's be straight about that last row.
Can you post an lpic.cc link on PTT and have it auto-open? Not right now
Before writing this, I double-checked how lpic.cc's own share links are structured. What you get after uploading today is a https://lpic.cc/{short-code} page link — not a direct file link ending in an image extension like i.imgur.com/xxx.jpg. That means none of the four rule sets catch it: not www.ptt.cc's extension rule, not term.ptt.cc's or PttChrome's domain allowlists. The share page itself does render a thumbnail preview — but only once someone opens it, not as an auto-expanding embed the moment you paste the link.
No kidding, that's not great news if auto-embedding is what you're after, and I'm not going to spin it into something it isn't. If your goal is "paste link, app shows thumbnail instantly," pick one of the hosts checked off above — Imgur, meee, or anything on term.ptt.cc's default allowlist. Where a share-page model like lpic.cc's actually earns its keep is elsewhere: password protection, view counts, and comment threads on the page itself — useful when what you care about is controlling who sees something and whether it gets logged, like transaction screenshots or anything you'd rather not have every random reader auto-preview. Those are two different needs, and forcing one tool to do the other's job never feels good.
So which one should you actually use?
If all you want is instant auto-embedding: it depends on which client your audience mostly uses. Mobile-app-heavy crowd — go with Imgur, or meee if you're in the habit of appending the extension yourself. Web-article-heavy crowd — any host with a standard-extension direct link works, just remember WebP is a dead end on www.ptt.cc web articles. term.ptt.cc users — check whether your host is already on your personal allowlist first, and add it manually if it isn't.
If you need something that works across every client, Imgur is still the only option all four rule sets accept — at the cost of Imgur having blocked uploads from Taiwanese IPs, a separate headache I cover in more depth in my PTT image posting tutorial. Honestly, there isn't a single host that removes format anxiety in every scenario. I've been burned by this enough times that I'm not going to pretend otherwise for the sake of promoting any particular one.
FAQ
Q1: Why did the same Imgur link auto-embed yesterday and not today?
Imgur has been blocking Taiwanese IPs since May 2025 — if you're browsing from Taiwan, you might not even be able to reach i.imgur.com at all, which has nothing to do with any PTT client's rules. Separately, PttChrome force-rewrites Imgur links to end in .jpg; if the original image is a transparent PNG, you may lose quality or transparency, but that only affects how it looks, not whether it renders at all.
Q2: Can I edit term.ptt.cc's trusted-domain list myself?
Based on the source, parseTrustedDomains supports reading a custom list, so yes — this is meant to be adjustable, not a hardcoded rule. I haven't personally tested where in the settings UI you'd do this or whether a page refresh is required afterward, so I'd point you to term.ptt.cc's own settings menu to look for it directly.
Q3: Why can't you give a definitive answer on whether mobile apps check a domain allowlist?
Because Mo PTT, JPTT, and PiTT are all closed-source, and I have no public repository to check line by line. Everything in this article about those three apps comes from community reports on PTT's ask board, not from me disassembling the apps myself. I've already flagged that as unverified above, and I'm not going to quietly upgrade it to a confirmed claim here.
Q4: Why doesn't www.ptt.cc support WebP when term.ptt.cc does?
Because they're two completely independent codebases — one is server-side Go (pttweb), the other is client-side JavaScript (ptt-term), maintained by different people at different points in time. WebP adoption came relatively late, and the pttweb rule clearly never got updated to match. That's really the core point of this whole piece: PTT isn't one unified system, it's a handful of independently maintained pieces of software stitched together.
Q5: What's the closest thing to a link that auto-embeds everywhere on PTT?
There's no single link that covers every scenario, but the closest you'll get: make sure your host's direct link ends in a standard extension (.jpg/.png/.gif — don't rely on WebP alone), skip any query string, and prefer a host that's already on term.ptt.cc's default allowlist (Imgur, meee, duk.tw, ImgBB, and Postimages all qualify). PttChrome users don't have much room to maneuver — right now it's really just Imgur and Flickr.
References
- [Question] Which image hosts support PTT auto-embed — PTT ask board
- Re: [Question] Which image hosts support PTT auto-embed — PTT ask board
- ptt/pttweb — PTT BBS web frontend source,
richcontent/url_based_finder.go - ptt/ptt-term — term.ptt.cc source,
src/plugins/media_previewer/image_preview_util.js - iamchucky/PttChrome — PttChrome source,
js/term_view.js - Complete 2026 guide to posting images on PTT — lpic.cc blog