/DOCS · OPEN SOURCE · MIT
734 animated ASCII art pieces you can add to any project. Put one on a web page with one tag, play it in a terminal, import it from npm, or let your coding agent add it in one prompt. Everything here is MIT licensed, with the source on GitHub.
npx ascii-magic-art<script type="module" src="https://www.ascii-magic.com/ascii/ascii.js"></script>
<ascii-art piece="matrix-rain"></ascii-art>npm install ascii-magic-artThe library is open source under the MIT License. The code lives at github.com/kailashsr38/ascii-magic-art and the package is ascii-magic-art on npm. You can use every piece in personal and commercial work, change it, and ship it. Credit is not required, though a link back to the library is appreciated.
<ascii-art> element, the looks that redraw any piece in other characters, the terminal player, and the drawing toolkit the pieces are built with.The fastest way to use the library is to let your coding agent do it. Run this in any terminal:
npx ascii-magic-artAn intro plays, then every piece plays live in your terminal. Move around with the keys below. When you find one you like, press enter: a prompt for that piece is copied to your clipboard. Paste it into Claude Code, Cursor, Copilot or any other coding agent, and it adds the piece to your site.
| Key | What it does |
|---|---|
| ← → | Previous or next piece |
| ↑ ↓ | Previous or next category |
| s / S | Next or previous look: Halftone dots, ASCII, Dense ASCII, Numbers, Binary, Letters, Blocks, Squares, Lines, Dither |
| a | Redraw text and line art in the look too |
| enter | Copy the prompt for this piece, in the look you picked, and exit |
| c | Copy the current frame as plain text |
| q, esc | Quit |
If you already know the piece, skip the browsing: npx ascii-magic-art prompt matrix-rain prints the prompt and copies it. Run npx ascii-magic-art prompt on its own for a prompt that lets the agent pick a piece itself. This is the prompt you get:
Add the animated ASCII art piece "matrix-rain" (Digital Rain) from ASCII Magic to this project.
1. Load the script once, in the browser only (in SSR frameworks such as Next.js, load it on the client):
<script type="module" src="https://www.ascii-magic.com/ascii/ascii.js"></script>
2. Put the piece where it fits best, such as the hero, a loading state, an empty state or the 404 page:
<ascii-art piece="matrix-rain"></ascii-art>
3. Keep a real heading or text next to it (the art is decoration), and size it with the size attribute or CSS.
Preview and options: https://www.ascii-magic.com/ascii/matrix-rain
Rules for coding agents: https://www.ascii-magic.com/ascii/use/ai-coding-agentsLoad the script once, then place the element wherever the art should go. The piece value is the name in the URL of each piece's page, for example matrix-rain for ascii-magic.com/ascii/matrix-rain.
<script type="module" src="https://www.ascii-magic.com/ascii/ascii.js"></script>
<ascii-art piece="matrix-rain"></ascii-art>
<ascii-art piece="spinning-torus" size="10" look="dots"></ascii-art>| Attribute | What it does | Default |
|---|---|---|
piece | Which piece to play (required) | |
size | Font size in px; the art scales with it | 12 |
speed | Playback speed, 1 is normal | 1 |
still | Show one frame, no animation | off |
bg | Background color behind the art | transparent |
look | Redraw it in another set of characters: dots, ascii, dense, numbers, binary, letters, blocks, squares, lines, dither | original |
chars | Your own characters instead of a look, for example chars=" .oO@" (sorted light to dark for you) | |
all | With look or chars, redraw text and line work too, not only shading | off |
mono | One color (the element's CSS color) instead of the piece's palette | off |
contrast | 0 to 100 | 0 |
dot-size | Halftone dot size for the dots look, 25 to 120 | 51 |
density | Halftone dot spacing, 40 to 250: more dots, same size | 131 |
steps | Halftone dot sizes: 3, 5, or 0 for smooth |
The element draws on a canvas, loads only the piece it needs (a few kilobytes), and animates only while it is on screen. Visitors who prefer reduced motion see a still frame. It has role img and an aria-label with the piece name, so keep a real heading or text next to it: the art is decoration. Changing an attribute restarts the piece, so you can switch pieces from your own code with el.setAttribute("piece", "heart-3d").
The element works in any framework, because it is a standard custom element. The only rule: load the script in the browser, once.
// app/layout.tsx
import Script from "next/script";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Script type="module" src="https://www.ascii-magic.com/ascii/ascii.js" strategy="afterInteractive" />
</body>
</html>
);
}
// any component
export function Hero() {
return <ascii-art piece="matrix-rain" size="10"></ascii-art>;
}// ascii-art.d.ts (React 19 types; with React 18, use "declare global" instead)
import type { DetailedHTMLProps, HTMLAttributes } from "react";
type AsciiArtProps = DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement> & {
piece: string;
size?: string | number;
speed?: string | number;
look?: string;
chars?: string;
bg?: string;
};
declare module "react" {
namespace JSX {
interface IntrinsicElements {
"ascii-art": AsciiArtProps;
}
}
}// vite.config.ts (Vue)
import vue from "@vitejs/plugin-vue";
export default {
plugins: [vue({ template: { compilerOptions: { isCustomElement: (tag) => tag === "ascii-art" } } })],
};
// nuxt.config.ts (Nuxt)
export default defineNuxtConfig({
vue: { compilerOptions: { isCustomElement: (tag) => tag === "ascii-art" } },
app: { head: { script: [{ src: "https://www.ascii-magic.com/ascii/ascii.js", type: "module" }] } },
});
<!-- any template -->
<ascii-art piece="matrix-rain"></ascii-art><!-- src/app.html (SvelteKit), inside <head> -->
<script type="module" src="https://www.ascii-magic.com/ascii/ascii.js"></script>
<!-- any component -->
<ascii-art piece="matrix-rain"></ascii-art>---
// src/layouts/Layout.astro
---
<script is:inline type="module" src="https://www.ascii-magic.com/ascii/ascii.js"></script>
<slot />
<!-- any page -->
<ascii-art piece="matrix-rain"></ascii-art>If you would rather not load anything from ascii-magic.com, serve the files from your own site. Install the package and copy three folders into your static folder; the element finds the pieces next to it.
npm install ascii-magic-art
mkdir -p public/ascii-magic-art
cp -r node_modules/ascii-magic-art/{runtime,pieces,lib} public/ascii-magic-art/<script type="module" src="/ascii-magic-art/runtime/ascii.js"></script>
<ascii-art piece="matrix-rain"></ascii-art>Copy the folders rather than bundling runtime/ascii.js: the element loads each piece on demand from the pieces folder beside it.
The same package plays pieces in color in any terminal with Node 18 or later. Press any key to stop a piece.
npx ascii-magic-art # browse everything, enter copies a prompt
npx ascii-magic-art moonlit-sea # play one piece
npx ascii-magic-art matrix-rain --look=binary
npx ascii-magic-art sleeping-cat --frame # print one still frame and exit
npx ascii-magic-art --list # every piece name# ~/.zshrc or ~/.bashrc: three seconds of art, only in an interactive terminal
[ -t 1 ] && npx --yes ascii-magic-art spinning-torus --seconds=3 2>/dev/null# a still frame as your server's message of the day
npx --yes ascii-magic-art moonlit-sea --frame > /etc/motd| Flag | What it does |
|---|---|
--look=dots | Redraw in a look: dots, ascii, dense, numbers, binary, letters, blocks, squares, lines, dither |
--chars=" .oO@" | Redraw in your own characters |
--all | With a look, redraw text and line work too |
--mono | One color |
--seconds=3 | Stop on its own after that many seconds (for shell startup) |
--frame | Print one frame and exit; add --t=2.5 to pick the moment |
--keep | Leave the last frame on screen when it stops |
prompt [piece] | Print and copy the prompt for a coding agent |
Colors turn off when the output is piped or when NO_COLOR is set. Big photo scenes shrink to fit the window in the browser.
Every piece is a small ES module with no dependencies apart from the toolkit in lib/kit.js. It exports meta and a create() function that returns draw(t): give it a time in seconds and it returns a frame.
import create, { meta } from "ascii-magic-art/pieces/spinning-torus.js";
const draw = create();
const frame = draw(1.5); // a string, or { text, color }
console.log(frame.text ?? frame); // meta.cols x meta.rows charactersimport { play } from "ascii-magic-art/runtime/player.js";
import * as piece from "ascii-magic-art/pieces/matrix-rain.js";
// a <pre> with a monospace font; the player draws a canvas over it
const stop = play(document.querySelector("pre"), piece, {
speed: 1,
look: { look: "dots" },
});
// later: stop();import { restyle, withLook } from "ascii-magic-art/runtime/glyphs.js";
import create, { meta } from "ascii-magic-art/pieces/heart-3d.js";
const draw = create();
const inDots = restyle(draw(1), meta.palette, { look: "dots", all: true });
const drawInBinary = withLook(create(), meta.palette, { look: "binary", all: true });| meta field | Meaning |
|---|---|
slug | The piece name, same as the file name |
name | Display name |
category | Category id (see categories.json) |
note | One line describing it |
tags | Search tags |
cols, rows | Exact frame size in characters |
fps | Frames per second it is designed for |
palette | Map from color key to hex, used by the color layer |
cell | "square" for photo-like scenes drawn on square cells |
A colored frame is { text, color }: two strings of the same shape, where each character of color is a key into meta.palette and a space means the default ink. frameHTML(frame, palette) in runtime/player.js turns a frame into HTML spans, and runtime/canvas.js draws frames to a canvas for images and video.
Any piece can be redrawn in another set of characters. Each cell's darkness comes from how much ink its glyph covers and how bright its color is; the look's characters are sorted by ink and the closest one is drawn. By default only shading is redrawn, so text and line work stay readable; all redraws everything.
| Look | Characters |
|---|---|
dots Halftone dots | ·•● |
ascii ASCII | .,-~:;=!*#$@ |
dense Dense ASCII | .'`^",:;Il!i><~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$ |
numbers Numbers | 1723456980 |
binary Binary | 01 |
letters Letters | ilcoeaxkdbAHMW |
blocks Blocks | ░▒▓█ |
squares Squares | ·▪■ |
lines Lines | ╌─━═ |
dither Dither | Square pixels switched on and off by an 8×8 Bayer pattern; as text, the same ordered dither in █ and spaces |
Every piece page on the site exports the piece the way you set it up: GIF, MP4 or WebM video (1920×1080 by default, 4K optional) and PNG wallpapers and social sizes (desktop, phone, YouTube thumbnail, GitHub social preview, headers, square posts and stories). For a GitHub README, export a GIF and commit it, or make an animated SVG title with the README banner maker. The use-case guides have live builders for READMEs, 404 pages, loaders, terminals, wallpapers and more.
Clone the repository, add a file to pieces/, and build each frame on a Grid:
import { Grid } from "../lib/kit.js";
export const meta = {
slug: "my-piece", name: "My Piece", category: "algorithms",
note: "One line about it.", tags: ["loop", "minimal"],
cols: 60, rows: 20, fps: 24,
};
export default function create() {
const g = new Grid(meta.cols, meta.rows);
return (t) => {
g.clear();
g.text(2, 2, "hello " + Math.floor(t));
return g.frame();
};
}git clone https://github.com/kailashsr38/ascii-magic-art.git
cd ascii-magic-art
node scripts/validate.mjs my-piece # size, colors, motion, under 12 ms a frame
node scripts/stress.mjs my-piece # boxes and text that break over 60 seconds
node bin/cli.js my-piece # watch it in your terminal| Grid method | What it draws |
|---|---|
set(x, y, ch, co) | One character, with an optional color key |
setZ(x, y, z, ch, co) | Depth-tested character, for 3D |
text(x, y, s, co) | A string |
block(x, y, s, co, solid) | A multi-line block; spaces are transparent unless solid |
hline / vline | Horizontal and vertical lines |
box(x, y, w, h, style, co) | A box with light, heavy, double or round corners |
fill(x, y, w, h, ch, co) | A filled rectangle |
line(x0, y0, x1, y1, ch, co) | A straight line |
circle(cx, cy, r, ch, co) | An ellipse corrected for tall cells |
shade(fn) | Calls fn(x, y, u, v) for every cell |
frame() | The frame to return: text, or { text, color } |
The toolkit also exports ramp and RAMPS (brightness to character), rng, noise2 and fbm (seeded randomness and noise), hsl, palette and gradient (colors), and rotX, rotY, rotZ, project and wire for 3D. To add your piece to the library, open a pull request on GitHub with the validator passing.
/FAQS
Licensing, frameworks, self-hosting, the terminal player and making your own pieces.