Skip to content
ToolsNow
Guides All tools

ASCII, ANSI and Unicode art explained

Character brightness ramps, why monospace is non-negotiable, how terminal colour actually works, and the platform formatting problems that break text art.

Published

Three things get called “ASCII art” and only one of them is ASCII. The distinction is not pedantry — it decides where your art will display correctly and where it will arrive as a column of question marks.

  • ASCII art uses the 95 printable characters of the 1963 US-ASCII set. Displays essentially anywhere.
  • ANSI art adds escape sequences that tell a terminal to change colour. The characters are still ASCII; the colour is instructions.
  • Unicode art uses block, shading and box-drawing characters — ▓ ░ ─ ┌ — which give far smoother results wherever the displaying font actually contains them.

The brightness ramp

Image-to-text conversion rests on one substitution: a character’s ink coverage stands in for a pixel’s brightness. @ fills most of its cell, . fills very little, and a sequence ordered by coverage becomes a greyscale.

A short ramp people use constantly:

@%#*+=-:.

And a longer one, from Paul Bourke’s much-copied page, giving about seventy levels:

$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`'.

Two things about ramps are not obvious.

The order is not the ASCII order, and it is not stable across fonts. Whether & is darker than W depends on the typeface. Ramps are hand-tuned for typical monospace faces, and a ramp that is merely “some punctuation in an arbitrary order” produces noise rather than an image.

The ramp should end in a space. Pure white is extremely common — any photograph with a sky or a highlight — and it must map to blank. A ramp without a trailing space renders highlights as . and the whole image acquires a grey haze.

The aspect-ratio trap

This is the single most common mistake, and it is invisible until someone points at it.

A monospace character cell is roughly twice as tall as it is wide. Sample one square region of the image per character and the output comes out stretched to double height — a face becomes a long oval and nobody can quite say why.

The fix is to sample regions about twice as tall as they are wide, or equivalently to compute the row count as:

rows = (imageHeight / imageWidth) × columns ÷ 2.1

The exact ratio varies by font; anything between 1.8 and 2.2 looks right.

Monospace is not a preference

Every character must occupy an identical cell. In a proportional font an i is much narrower than an m, so each line ends at a different place and the image collapses into diagonal mush.

This is why almost every “why does my ASCII art look broken” question resolves to the destination not using a monospace font. The practical answer is therefore not to choose a font but to use a code block, which forces one.

Even in monospace, one hazard remains: characters outside the basic Latin range are frequently not monospaced in the same font, because they come from a fallback font with different metrics. Emoji are the worst offender — most render double-width, and a single emoji shifts an entire line.

Terminal colour, and what ANSI actually is

ANSI art has no colour information in its characters. Colour comes from escape sequences: a control character followed by a code the terminal interprets rather than prints. The relevant ones are standardised in ECMA-48.

Three generations coexist:

  • 16 colours — the original, universally supported.
  • 256 colours — a fixed palette, near-universal today.
  • 24-bit true colourESC[38;2;R;G;Bm, supported by most modern terminals but not all.

Crucially, the escape sequence set includes far more than colour: sequences that move the cursor, clear the screen, and on some terminals set the window title. A file of escape sequences from an untrusted source is therefore not inert, which is a real if uncommon category of trick. A generator that emits only colour and reset codes is making a deliberate safety choice, and it is worth knowing whether the one you use does.

To view an ANSI file, cat it. Opening it in a text editor shows the escape codes as literal garbage, because an editor prints them rather than interpreting them.

Unicode blocks: better tone, worse portability

The Unicode Block Elements range gives four solid shading levels — █ ▓ ▒ ░ — which produce visibly smoother gradients than punctuation ever will, because each glyph really is a uniform block of a given density rather than a shape that happens to cover some proportion of its cell.

Half-blocks are the clever trick: ▀ and ▄ let one character cell hold two independently coloured pixels, doubling vertical resolution. Combined with 24-bit colour this is how modern terminal image viewers get results that look genuinely like photographs.

Box-drawing characters (─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼) are the other useful range, and are what tables and frames in terminal interfaces are built from.

The cost is portability. These characters need a font that contains them. Falling back means substituted glyphs with different widths, and the alignment is gone. If the destination is unknown, plain ASCII is the safer answer, which is why a “plain ASCII only” option is worth having.

Platform formatting problems

Markdown and GitHub. Use a fenced code block. Without one, Markdown collapses runs of spaces and may interpret *, _ and # as formatting — all of which appear in ramps.

Backticks inside the art. Art containing ``` closes its own fence and the remainder renders as markup. The fix is to use a fence longer than any run of backticks in the content; a generator that does not do this will eventually produce output that breaks the page it is pasted into.

Discord. Code blocks work, and messages are capped at 2000 characters, which ASCII art reaches quickly. A 100-column image of 40 lines is already 4000 characters. Reduce the width or send a file.

HTML. Use <pre>, and escape the content. This is not theoretical: the long ramp above contains <, > and &, so unescaped output is a live injection point the moment someone pastes it into a page.

Source-code comments. A block comment containing */ ends early and spills the rest of the art into the file as syntax errors. Line comments (#, //) have no such problem and are the safer choice.

Email and chat. Most clients use proportional fonts by default and will destroy the alignment regardless of what you do. Send an image instead.

When to convert to an image

There is a point at which fighting the destination is not worth it. If the art must survive a proportional font, an unknown Unicode font, a character limit or a platform that re-wraps text, render it to PNG in a monospace font and send that. You lose selectability and searchability, and you gain the guarantee that it looks the same everywhere.

Sources and further reading

Last reviewed 31 July 2026.