Welcome to my documentation of the Tab Exploit and a showcase of my tool to embed pictures in BBCode even when images are disabled. NationStates is a game where you run a nation and it also has a phpBB-forum, where you can make a signature. It can however only be 800 characters long and cannot contain any external images or animations. However, I discovered a glitch to bypass this rule, allowing us to embed images. This documentation is a history of the exploit and a brief presentation of KopiBildero, a web tool, which easily transforms your image into an embeddable format. I love console homebrew and emulation - so this exploration has been a lot of fun for me!
The Beginnings#
When I started playing my nation, I wanted to have a good and unique signature. I once saw a nation with a flag in their signature - back then flags were pretty much the only kind of image you could find in someone’s signature. In most cases flags were simply a character like -
or .
where both the character and the background had the same colour. After some experimentation, I started using tabs or [tab=1][/tab]
. Tabs have the neat property that they’re invisible if the user tries to copy them, appearing more like a real image. It was thus possible to encode a pixel of the colour XYZ
as [background=XYZ][colour=XYZ][tab=1][/tab][/colour][/background]
.
That way I implemented my first flag (and yes it was just a blue Bremen flag 😅) in the signature as follows: BBCode [box][floatleft][size=16][align=center][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=#FFFFFE][color=#FFFFFE][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=20][/tab][/color][/background][/align][align=center][background=white][color=white][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=white][color=white][tab=20][/tab][/color][/background][/align][align=center][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=#FFFFFE][color=#FFFFFE][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=20][/tab][/color][/background][/align][align=center][background=white][color=white][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=white][color=white][tab=20][/tab][/color][/background][/align][align=center][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=#FFFFFE][color=#FFFFFE][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=20][/tab][/color][/background][/align][align=center][background=white][color=white][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=white][color=white][tab=20][/tab][/color][/background][/align][align=center][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=#FFFFFE][color=#FFFFFE][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=20][/tab][/color][/background][/align][align=center][background=white][color=white][tab=2][/tab][/color][/background][background=#00BFFF][color=#00BFFF][tab=2][/tab][/color][/background][background=white][color=white][tab=20][/tab][/color][/background][/align][/size][/floatleft][/box]
The result was something like this:
Woah that looks neat! Note that the flag is not copyable and is not a svg. Firstly, how does this even fit within the 800 character limit? Well the individual characters within the brackets do not count and seemingly the [background]
and [colour]
tags themselves aren’t counted either. Back then however I still thought that the individual tabs get counted as characters. So before we continue, what do the individual elements do? Well in essence, the whole string must be attached together without whitespaces, as these add empty lines between rendered rows. Additionally, so that each line is neatly stacked on top of each other, each line must be enclosed with [align=center] ... [/align]
But even that is not sufficient, the whole string also needs to be enclosed in either [floatleft][/floatleft]
or [floatright][/floatright]
. These findings were found experimentally.
The next thing we need to discuss is the [size=16]
modifier. Normal text size corresponds to [size=100]
, but such an image would be way too big. One might think, that reducing the size by let’s say 50% would also simply reduce the image size by 50% while preserving the aspect ratio, but this doesn’t really happen. Instead, the image shrinks vertically in one dimension. To demonstrate this I will take the square image of a pansy, but note that by that point I did not work with images yet, only with flags. However, the square pansy image is excellent to demonstrate the transformations visually, as flags have more exotic aspect ratios.
size=8, tab=2 | size=15, tab=2 | size=23, tab=2 |
---|---|---|
![]() | ![]() | ![]() |
Increasing the size stretches the image vertically as seen in the three images above, where tab=2
but size=8
, 15
, and 30
. If we increase the tab length, we perform horizontal stretching, so we need to also increase size as well—otherwise we get the following result:
size=15, tab=1 | size=15, tab=2 | size=15, tab=3 |
---|---|---|
![]() | ![]() | ![]() |
In essence the formula for the size to tab ratio is \(\text{size}= 8 \cdot \text{tab}_\text{length}\). Or with other words we can describe the proportions-respecting transformation using the following matrix where \(t\) the tab length, \(w\) is the width, \(h\) the height:
\( \begin{smallmatrix} w_{\text{new}}\ h_{\text{new}} \end{smallmatrix} \)
Nice so we now know how to encode flags in NS signatures and in my example above I had 160 tab characters in total. Already back then I noted that increasing the flag size and inserting multiple flags does not trigger the 800 character limit, even when the number of tabs exceeds 800. Thus, I really wanted to examine this, but I didn’t have the necessary time till October 2025.
The Experimentation#
Since the transformation formula is relatively easy, I decided to write a web app to perform the transformation from an image to BBCode. I also wanted to learn how to write Firefox extensions, so this was a prime opportunity to get started. This is how KopiBildero (Esperanto for “copy pixel”) was born. The JavaScript program essentially creates a string that can be copied into NationStates.
KopiBildero reads every individual pixel of an image, extracts its RGBA value, and transforms it into my BBCode format. The very first picture I tested was test28x28, a minified picture of a pansy flower. Why 28x28 pixels? Because that’s the largest possible size before hitting 800 characters. But I wanted bigger pictures, and since I suspected that tab isn’t treated like any other BBCode element, I transformed a 40x40 image of a pansy into BBCode. Eureka! My suspicions were confirmed! The 800-character limit was surpassed, and the image rendered in its glorious 40p!
I continued my tests all the way up to 90x90 pixels. Images bigger than 90x90 pixels cannot be rendered. However! Though 100p or higher images cannot be rendered, they do not cause BBCode to return an error message, which is why I firmly believe that this is an unintended glitch.
But can we insert even larger images somehow? The answer is a clear yes! The Tab Exploit allows us to insert multiple pictures next to each other!
What’s the limit to how many pictures we can insert? I didn’t find any 😅, which is yet another clue that this is not intended. Unfortunately, when we exceed the 800-character rule by more than 80,000 characters, the forum begins to slow down. It didn’t only slow down for me, but for other users as well!
That is really unfortunate, because it means that although we can technically inject images larger than 90x90, we pay a hefty price and ruin the experience for others. I think that the forum works well up to two 90x90 images in the signature; anything above that begins to slow the website down, with both Blink-based and Gecko-based browsers affected.
But two 90p images are still very cool, and I decided to use my tool to embed my nation’s countryball and mascot into my own signature, at least before this glitch gets patched out 🙂.
The Tool#
All of this was facilitated using KopiBildero, which I programmed to become an easy-to-use extension for Firefox. It can import images of any size and automatically resizes them to 90x90. Though it is possible to input and pixelise smaller images as well. The user simply needs to select the image file and copy the string into their signature. The user can also input the desired output size (tab length) of the image, as the program handles the transformation itself. In addition, the user can choose whether the image should stick to the left or to the right.
Unfortunately, the moderation is not a fan of the images on the basis that they far exceed the 8-line limit. Which… yeah… they do by at least 82 lines 😅. The tech team is now examining the exploit and I’m very satisfied for finding a neat BBCode glitch and for using it to inject images 🤩.
Reply by Email