BBCode to HTML: A Practical Guide to Converting Forum Markup
How BBCode bracket tags map to HTML, with a worked example, rules for nesting and links, and a safe way to migrate old phpBB or vBulletin posts to a modern site.
BBCode to HTML: A Practical Guide to Converting Forum Markup
If you have ever run a forum, you know BBCode. It is the bracket-tag markup that phpBB, vBulletin, and a hundred other boards hand their users instead of raw HTML. You write [b]bold[/b], the forum shows bold, and nobody gets to paste a <script> into a thread. It worked for two decades. The problem starts the day you want that content to live somewhere else — a blog, a static site, a headless CMS. Browsers do not speak BBCode. Square brackets render as square brackets. So you have to translate.
This post is about that translation: what the tags actually map to, where the edge cases hide, and how to move a pile of old posts across without breaking your new pages.
The bracket syntax, tag by tag
BBCode mirrors HTML almost one-to-one, which is exactly why the conversion is mechanical. Every tag is a keyword wrapped in square brackets, with a matching closing tag that adds a slash. [b]text[/b] becomes <strong>text</strong>. The rest follow the same shape:
[i]becomes<em>,[u]becomes<u>,[s]becomes<s>.[color=red]hi[/color]becomes<span style="color:red">hi</span>.[size=18]big[/size]sets an inline font-size.[quote]becomes<blockquote>, and[quote=name]keeps the attribution.[list]with[*]items becomes a<ul>with<li>children.[center],[email], and[code]each map to their HTML equivalent.
The two tags people get wrong are the ones that carry a value. [url=https://toolora.app]Toolora[/url] becomes <a href="https://toolora.app">Toolora</a>. A bare [url]https://toolora.app[/url] with no value reuses the address as both the href and the visible link text. And [img]https://example.com/pic.png[/img] becomes an <img> tag pointing at that source. The value after the = is the attribute; the text between the tags is the content. Once you see that pattern, the whole language reads like HTML with rounder corners.
Tags nest, and order matters
BBCode nests the same way HTML does, and a real converter has to honor that. A line like [b][color=blue]Sale[/color][/b] should produce HTML that is both bold and blue:
<strong><span style="color:blue">Sale</span></strong>
The converter walks every tag in sequence, so the inner span lands inside the outer strong, and the browser renders the combined effect. This is also where unclosed tags bite. A lone [b] with no matching [/b] is not a thing the converter should guess about. The safe behavior is to leave it as plain text — the visible characters [b] — rather than inventing a closing tag and reflowing everything after it into bold. If you have ever watched a single missing </div> swallow half a page, you understand why "leave it literal" beats "guess the structure."
A worked example
Here is a small forum post with a quote, a styled line, and a link. This is the kind of thing you would paste into the BBCode to HTML converter:
Input BBCode:
[quote=admin]Read the rules before posting.[/quote]
[b]New release[/b]: grab it from [url=https://toolora.app]our site[/url].
[color=green]Thanks everyone![/color]
Output HTML:
<blockquote><cite>admin</cite>Read the rules before posting.</blockquote>
<strong>New release</strong>: grab it from <a href="https://toolora.app">our site</a>.
<span style="color:green">Thanks everyone!</span>
Every bracket pair turned into a known HTML element, the quote attribution survived as a <cite>, and the link carried its label across. Nothing was left to interpretation. Paste that block into any editor that accepts HTML and it renders exactly as the original post did.
Why escaping comes first
Here is the part that separates a toy regex from something you can trust. A good converter escapes the raw text to entities — &, <, >, ", ' — before it touches a single BBCode tag. Only then does it turn the specific tags you wrote into a fixed, known set of HTML elements.
That ordering is the whole safety story. If someone pasted <script>alert(1)</script> into a forum post, the escape pass converts it to harmless visible characters before any tag matching runs. It can show up on your page as text, but it can never execute. The same protection covers URLs: a quote or angle bracket inside an [url] value gets escaped, so it cannot break out of the href attribute and inject extra markup. And anything between [code] and [/code] is held literal — HTML-escaped, wrapped in <pre><code>, and never parsed as BBCode — so [code][b]not bold[/b][/code] shows the actual characters [b]not bold[/b] in a code block. That is precisely what you want when you are writing a tutorial about BBCode itself.
If you need to go the other direction and neutralize a chunk of raw HTML before storing it, an HTML entities encoder does that single job in isolation.
Migrating an old forum without breaking pages
I migrated a phpBB board to a static site last year, and the thing that surprised me was how much sheer noise lives in old posts. People paste stack traces, half-finished XML, angle brackets from chat logs — content that would shatter naive find-and-replace. The escape-first approach is what made it survivable: I could feed in years of threads, full of stray < characters and pasted code, and every one came out as valid HTML with the quotes, code blocks, and links intact. Not a single post smuggled markup into the new template, because the brackets were already neutralized before any tag ran. I batched the posts, eyeballed the live preview for a few of the gnarliest threads, and copied the source straight into the new editor.
A few habits made it smooth:
- Close your tags. If a legacy post has an orphaned
[quote], fix it at the source before converting, or accept the literal bracket in the output. - Decide on unknown tags up front. Boards accumulate custom tags like
[spoiler]or[marquee]. You can keep them verbatim as escaped text to clean up by hand, or strip the tag and keep the inner text. Either way they never become live HTML. - Spot-check the preview, not just the source. A live render catches a broken list or a runaway color faster than reading raw HTML does.
If your target system prefers Markdown over HTML, convert to HTML first and then run the result through an HTML to Markdown converter for the second hop.
Where to draw the line
BBCode to HTML is a translation, not a rewrite. The converter should reproduce what the post said, with the same emphasis, the same links, the same structure — and nothing more. Resist the urge to "improve" the markup mid-conversion. If you want to flatten styling or remove tags entirely after the fact, that is a separate, deliberate step you can run on the HTML output later.
The payoff is that a fifteen-year-old forum thread becomes a clean, safe block of HTML you can drop into any modern page without holding your breath. The brackets go in, real elements come out, and the script-shaped landmines in old posts stay defused.
Made by Toolora · Updated 2026-06-13