# Docs: the open-source animated ASCII art library

Source: https://www.ascii-magic.com/ascii/docs (ASCII Magic library documentation)

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.

`One prompt`
```bash
npx ascii-magic-art
```

`Web page`
```html
<script type="module" src="https://www.ascii-magic.com/ascii/ascii.js"></script>

<ascii-art piece="matrix-rain"></ascii-art>
```

```bash
npm install ascii-magic-art
```

## Open source, MIT licensed

The library is open source under the MIT License. The code lives at [github.com/kailashsr38/ascii-magic-art](https://github.com/kailashsr38/ascii-magic-art) and the package is [ascii-magic-art on npm](https://www.npmjs.com/package/ascii-magic-art). 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](https://www.ascii-magic.com/ascii) is appreciated.

- **What is in it:** all 734 pieces (one small ES module each), the web player and the `<ascii-art>` element, the looks that redraw any piece in other characters, the terminal player, and the drawing toolkit the pieces are built with.
- **What is not:** the [ASCII Magic editor](https://www.ascii-magic.com/app), which turns your own photos and videos into ASCII, is a separate product.
- **One exception:** two photo-based scenes, Ocean Sunset and Starry Ridge, keep the Unsplash License of their source photos. They are listed in the NOTICE file.
- **Contributing:** issues and pull requests are welcome on GitHub, including new pieces (see [Make your own piece](https://www.ascii-magic.com/ascii/docs#make)).

## Add a piece in one prompt

The fastest way to use the library is to let your coding agent do it. Run this in any terminal:

```bash
npx ascii-magic-art
```

An 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:

`prompt.txt`
```text
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-agents
```

## Put a piece on a web page

Load 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](https://www.ascii-magic.com/ascii/matrix-rain).

```html
<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")`.

## React, Next.js, Vue, Svelte and Astro

The element works in any framework, because it is a standard custom element. The only rule: load the script in the browser, once.

`Next.js`
```js
// 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>;
}
```

`TypeScript`
```ts
// 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;
    }
  }
}
```

`Vue / Nuxt`
```ts
// 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>
```

`Svelte`
```html
<!-- 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>
```

`Astro`
```astro
---
// 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>
```

## Host it yourself

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.

```bash
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/
```

```html
<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.

## Play pieces in a terminal

The same package plays pieces in color in any terminal with Node 18 or later. Press any key to stop a piece.

```bash
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
```

`On every new shell`
```bash
# ~/.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
```

`MOTD`
```bash
# 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.

## Use pieces in your own code

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.

`Node`
```js
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 characters
```

`Browser`
```js
import { 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();
```

`Looks in code`
```js
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.

## Looks

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 |

## GIF, video and wallpapers

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](https://www.ascii-magic.com/ascii/banner). The [use-case guides](https://www.ascii-magic.com/ascii/use) have live builders for READMEs, 404 pages, loaders, terminals, wallpapers and more.

## Make your own piece

Clone the repository, add a file to `pieces/`, and build each frame on a `Grid`:

`pieces/my-piece.js`
```js
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();
  };
}
```

`Check it`
```bash
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.

## Library docs: frequently asked questions

Licensing, frameworks, self-hosting, the terminal player and making your own pieces.

**Q. Is the ASCII Magic library open source?**

Yes. The library is MIT licensed, with the source on GitHub (github.com/kailashsr38/ascii-magic-art) and the package on npm as ascii-magic-art. That covers all 734 pieces, the web player, the <ascii-art> element and the terminal player. The ASCII Magic editor is a separate product and is not part of the open-source package.

**Q. Can I use the pieces in commercial projects?**

Yes. MIT lets you use, change and ship the pieces in commercial work, including client sites and paid apps. Two photo-based scenes, Ocean Sunset and Starry Ridge, keep the Unsplash License of their source photos: you can still use them, but not sell them unaltered. The NOTICE file lists the details.

**Q. Do I need to credit ASCII Magic?**

No, credit is not required. Keep the MIT license text if you copy the source files into your own repository. A link back to ascii-magic.com[ASCII library](https://www.ascii-magic.com/ascii) is appreciated, because it helps other people find the library.

**Q. What does npx ascii-magic-art do?**

It opens a live browser of all 734 pieces in your terminal. Arrow keys move between pieces and categories, and enter copies a ready-made prompt for that piece to your clipboard. Paste the prompt into Claude Code, Cursor, Copilot or another coding agent and it adds the piece to your project.

**Q. How do I add animated ASCII art to a React or Next.js site?**

Load the script once on the client, then use the element. In Next.js, add the script with next/script in your root layout, and write <ascii-art piece="matrix-rain"></ascii-art> in any component. React 19 renders custom elements directly; in TypeScript, add a small declaration for ascii-art, shown in the frameworks section.

**Q. Does the embed slow down my page?**

Very little. A piece is a few kilobytes of JavaScript that loads when the element appears, draws on a canvas, and only animates while it is on screen. Visitors who prefer reduced motion get a still frame. For an above-the-fold hero, give the element a fixed size so the layout does not shift.

**Q. Can I host the files myself instead of loading them from ascii-magic.com?**

Yes. Install the package, copy its runtime, pieces and lib folders into your static folder, and point the script tag at runtime[ASCII library](https://www.ascii-magic.com/ascii).js in your copy. The element finds the pieces next to it, so nothing loads from ascii-magic.com.

**Q. How do I change the color of a piece?**

Add the mono attribute and set a CSS color on the element; the whole piece is then drawn in that one color. To change the characters instead, use the look attribute (for example look="dots" or look="binary") or chars with your own characters, light to dark.

**Q. Is it accessible to screen readers?**

The element has role img and an aria-label with the piece name, so screen readers announce it as one image instead of reading hundreds of characters. Without JavaScript nothing is drawn, so keep a real heading or text next to the art: treat it as decoration.

**Q. How do I make my own piece?**

Write one small ES module that exports meta and a create() function returning draw(t), usually with the Grid helper from lib/kit.js. Clone the GitHub repository, run node scripts/validate.mjs your-piece to check size, colors, motion and speed, and open a pull request if you would like it in the library.

**Q. Can I use the pieces in my own command line tool?**

Yes. Import a piece from the npm package, call create() once, then call draw(t) with the time in seconds and print the frame. Use frame.text for plain text, or map the color layer to ANSI colors as the bundled terminal player does in bin/cli.js.

**Q. Which looks can a piece be redrawn in?**

Original, Halftone dots, ASCII, Dense ASCII, Numbers, Binary, Letters, Blocks, Squares, Lines and Dither, or any characters you pass yourself. Looks redraw the shading of a piece; add the all attribute (or --all in the terminal) to redraw text and line work too.
