Images
Load a File, Blob or public URL with setImage(). Check the resolved success value, then wait for onFrame before exporting. Remote servers must allow cross-origin access.
From a shareable look to an interactive canvas. Start with a working example, then find the settings and lifecycle details you need.
One field. Four renderers. Move your pointer across the preview.
Start in the workspace without installing anything. This link loads a procedural field and a look; try it, change the settings, then use your own media.
https://ascii.cafe/app?v=1&s=orbit-sphere&cw=terminal&lv=8The workspace at /app turns a picture, a video, a camera or a shared screen into ASCII characters, halftone discs, ordered dither or line art, live. Lines includes engraving, flow and contour styles. Rendering and exports run in the browser without a visitor account. Optional feature submissions upload ASCII frame JSON, a cover image and chosen public credit after consent; original files stay local, but Show Original Background includes rendered source pixels in the submitted capture.
Shareable rendering settings live in the address bar. A link reproduces a look; a settings file carries the same keys as JSON. The Settings links section documents both.
Activate a Developer key in the workspace, then choose Developer > Download ZIP. The ZIP includes Artwork.jsx, standalone index.html, player modules, artwork.json and Setup.pdf. Bake Frames captures 1 to 30 seconds at 32 fps. Include Original Asset bundles the full image or video for live rendering. Keep the folder together for React and module integration. The standalone HTML works offline. The paths below are local filenames in your project, not public CDN downloads.
Bake Frames samples 1 to 30 seconds at 32 fps. Files and generated fields are sampled offscreen at exact times; camera and screen feeds record in real time with the tab visible. Include Original Asset bundles an image or video up to 128 MB and renders the full media live. Generated fields and live feeds use Bake Frames.
The player preserves the captured aspect ratio and scales to its container. Solid, linear and radial backgrounds retain their settings. Show Original Background includes rendered source pixels: baked backgrounds use JPEG or transparent PNG frames up to 960 pixels; original-asset mode retains source resolution. Halo and ripples remain interactive when enabled. Reduced motion holds the first frame and disables motion effects. Shimmer, Spotlight, Code Glitch, Flicker, Scanlines, Breathe, Heartbeat, Focus and Wipe operate on Characters with Alphabet style. Wave and Jelly bend Characters with Alphabet style and connected Lines. Contour Wave Motion sends one broad crest through whole contour strokes; Wavy Lines bends them with a rolling wave. Contour Wave Motion requires Contour Lines; Wavy Lines also supports Characters with Alphabet style and other Lines. Glow works across all algorithms. Baked frames retain their motion parameters; plain text has no position or glow channel.
Baked captures are limited to 32 million grid cells across all frames and 128 MB of artwork JSON. Lower density or duration if a bake is too large. A repeating baked segment can have a visible seam. Speed 0 holds the source. To change a baked look, export again. Keep all ZIP files together for React or module integration; the standalone index.html embeds its dependencies and artwork for offline playback.
Mount the engine into a sized element. Keep the returned instance to update settings or release it later.
<div id="stage" style="height:480px"></div>
<script type="module">
import GlyphRaster from "./glyph-raster.js";
const art = new GlyphRaster(document.querySelector("#stage"), {
ramp: " ·K■|", density: 90, pointerAmount: 0.5,
});
// Call art.destroy() when the host is removed.
</script>Import a generated component into a client component. Give its container a defined size.
// exported from the workspace
import Pour from "./Artwork.jsx";
export function Hero() {
return <Pour />;
}Host the standalone player alongside your site and give its iframe a descriptive title.
<iframe src="/artwork/index.html"
title="my pour"
style="width:100%;height:480px;border:0">
</iframe>Choose the source you own. Keep the same engine instance when the source or styling changes.
Load a File, Blob or public URL with setImage(). Check the resolved success value, then wait for onFrame before exporting. Remote servers must allow cross-origin access.
Use setVideo() for a file or URL, or setSource() with a video element you control. Decode a frame before capturing it.
Request access from a click on HTTPS or localhost. A settings link cannot grant permissions or restore a screen-sharing session.
// art is the engine instance from the entry-point example.
// file is a File from your image input.
const loaded = await art.setImage(file);
if (!loaded) throw new Error("Image could not load");
art.update({ density: 100, sourceFit: "width" });
// Wire this to a user click.
shareButton.addEventListener("click", () => {
art.enableScreenShare();
});
// Call this cleanup when the host unmounts.
function cleanup() {
art.destroy();
}Halo and ripples respond to input in a live player. PNG, GIF and MP4 preserve rendered pixels; they cannot respond to a new pointer after export.
art.update({
pointerAmount: 0.35,
pointerRadius: 0.25,
rippleAmount: 0.3,
rippleSpeed: 1,
pointerMask: "everywhere",
rippleMask: "everywhere",
});The engine supports the visitor’s reduced-motion preference. Keep decorative motion optional and provide a meaningful description for the canvas.
A touch preview should not capture every drag. Keep scrolling available and treat hover effects as an enhancement.
More columns mean smaller characters and more work per frame. Give the container a real height, then tune density and cadence together.
The engine that draws this site is one JavaScript file with no dependencies. It draws into a box you give it, takes one options object, and rendering settings can be changed in place while it runs. Pass onFrame and onStatus callbacks when constructing the engine.
It is not a free download. Using it in your own pages needs the developer license, which covers one commercial project. What the license includes is on the price board and in the license section below.
<div id="stage" style="height:480px"></div>
<script type="module">
import GlyphRaster from "./glyph-raster.js";
const art = new GlyphRaster(document.querySelector("#stage"), {
ramp: " ·K■|", density: 90, pointerAmount: 0.5,
});
// Call art.destroy() when the host is removed.
</script>The constructor is GlyphRaster and the file is glyph-raster.js.
Search by option, group or behavior. Defaults are the engine's own; the Values column notes workspace differences.
56 of 56 entries
| Name | Purpose | Values | Default |
|---|---|---|---|
markMotionMARKS AND ALPHABET | Mark-level animation. Wave and Jelly bend glyphs and connected lines; Shimmer, Spotlight, Code Glitch, Flicker, Scanlines, Breathe, Heartbeat, Focus and Wipe affect glyphs. Contour Wave Motion sends one broad crest through contour strokes; Wavy Lines bends glyphs and connected lines. The host supplies the phase. | none, wave, shimmer, spot, code, flicker, scan, breathe, jelly, beat, cascade, contourwave, focus, wipe | none |
markPhaseMARKS AND ALPHABET | Position in one repeating motion cycle, recorded in frame appearance for replay. | 0 to 1 | 0 |
markAmountMARKS AND ALPHABET | Strength of mark motion; zero draws the unanimated marks. | 0 to 1 | 0 |
sourceSOURCE AND FIT | What is drawn: a built-in moving field by id, or image, video, webcam or screen once one is attached. | orbit-sphere, gallop, drape, plasma, merge, converge, dispatch, sweep, image, video, webcam, screen | orbit-sphere |
thoughtSOURCE AND FIT | The seed phrase the fields are drawn from. The same phrase always draws the same motion. | any short string | a slow tide |
sourceFitSOURCE AND FIT | How a picture with its own aspect fills the lattice: cover it, or match its width or its height and band the rest. | cover, width, height | cover |
matInsetSOURCE AND FIT | An empty margin around the picture, in percent of the box. | 0 to 40 (workspace: 0 to 14) | 0 |
lineDirectionMARKS AND ALPHABET | Direction of line strokes without rotating the source. | vertical, horizontal | vertical |
portraitTextMARKS AND ALPHABET | Repeating text for typography; size and weight follow tone. | 1 to 96 characters | stay curious keep looking |
markTypeMARKS AND ALPHABET | How the image is drawn: characters, dots, lines, or repeating text. | glyph, dotRadius, ditherDot, engraving, flow, contour, typography | glyph |
rampMARKS AND ALPHABET | The alphabet, darkest first. A literal string; a leading space leaves the darkest cells empty. | 2 to 16 characters | ·K■| |
levelsMARKS AND ALPHABET | How many brightness levels the picture is cut into. Raised to the alphabet's length when it is longer. | 2 to 16 | 5 |
dotValueMARKS AND ALPHABET | Halftone only: the disc's alpha follows its level as well as its size. | true, false | false |
densityMARKS AND ALPHABET | Cells across the box. The cell size follows from the box's width. | a positive integer (the workspace pins the cell size and derives this) | 90 |
cellAspectMARKS AND ALPHABET | The width of a cell relative to its height. | 0.2 to 4 (workspace: 0.5 to 1.6) | 1 |
contrastTONE | Stretches or flattens the difference between dark and bright. | 0.05 to 8 (the workspace uses 0.6 to 2) | 1 |
brightnessTONE | Lifts or lowers the whole picture before it is cut into levels. | -1 to 1 (the workspace uses -0.5 to 0.5) | 0 |
ditherTONE | An ordered pattern that breaks up flat bands between levels. | 0 to 1 | 0 |
invertTONE | Swaps dark and bright. | true, false | false |
inkCOLOR | The color the marks are drawn in. An eight-digit value carries an alpha. | a CSS hex color | #ffffff |
groundCOLOR | The color behind the marks. | a CSS hex color | #000000 |
groundFillCOLOR | Paint the ground every frame, or clear to real alpha so exports carry transparency. | opaque, transparent | opaque |
inkModeCOLOR | Map foreground colors by brightness or across the canvas. | tone, gradient | tone |
inkAngleCOLOR | Foreground gradient angle. 90 runs left to right. | 0 to 360 | 90 |
inkPaletteCOLOR | One ink or custom palette stops; inkMode chooses brightness mapping or a spatial gradient. | single, custom | single |
paletteCOLOR | Custom colors: darkest first in tone mode, spatial stop order in gradient mode. | 2 to 16 hex stops, comma separated | #aa30be, #c742dd, #f3aeff, #ffffff |
keyColorsCOLOR | Removed colors: a cell whose source color matches one draws nothing. | up to 16 hex colors, comma separated; empty is off | empty |
keyToleranceCOLOR | How close a source color has to be to a removed color to count. | 0 to 1 | 0.18 |
groundSourceCOLOR | Show the original source behind the marks. | true, false | false |
groundOpacityCOLOR | Opacity of solid or gradient background paint, independent of marks. | 0 to 1 | 1 |
groundSourceOpacityCOLOR | Original source opacity over the background. | 0 to 1 | 1 |
groundModeCOLOR | Background fill shape. | solid, linear, radial | solid |
groundPaletteCOLOR | Background gradient stops. | 2 to 5 six-digit hex colors, comma separated | #101828, #312e81 |
groundAngleCOLOR | Linear gradient angle in degrees. | 0 to 360 | 90 |
keyTargetCOLOR | Layer affected by removed colors. | effect, background, both | effect |
keyTolerancesCOLOR | Per-color effect tolerance overrides. | JSON object mapping six-digit hex colors to 0 to 1 tolerances | empty |
backgroundKeyColorsCOLOR | Colors removed from the original background. | up to 16 hex colors, comma separated | empty |
backgroundKeyToleranceCOLOR | Default background color-removal tolerance. | 0 to 1 | 0.18 |
backgroundKeyTolerancesCOLOR | Per-color background tolerance overrides. | JSON object mapping six-digit hex colors to 0 to 1 tolerances | empty |
speedMOTION | How fast a field or a clip the engine owns plays. | 0 to 8; 0 holds the source | 1 |
pulseMOTION | A slow, even brightening and dimming of the whole picture. | 0 to 1 | 0 |
holdFpsMOTION | How many times a second the box redraws. | 1 to 240 (workspace default: 16) | 60 |
pointerAmountINTERACTION | How much the cells under the pointer brighten. | 0 to 1 | 0 |
pointerRadiusINTERACTION | How far the halo reaches from the pointer, as a share of the box. | 0.02 to 2 (workspace: 0.05 to 0.8) | 0.25 |
pointerMaskINTERACTION | Whether the halo lights empty cells too, or only cells that already carry a mark. | everywhere, foreground | everywhere |
rippleAmountINTERACTION | How strongly a click or a pointer trail sends a ripple. | 0 to 1 | 0 |
rippleSpeedINTERACTION | How fast a ripple travels. | 0.3 to 3 | 1 |
rippleMaskINTERACTION | Whether a ripple crosses empty cells, or only cells that already carry a mark. | everywhere, foreground | foreground |
rippleInkINTERACTION | Whether a rippled cell keeps its own ink, takes one color, or takes a color from ripplePalette by strength. | inherit, single, palette | inherit |
rippleColorINTERACTION | The ripple's color when rippleInk is single. | a CSS hex color | #ff6fd8 |
ripplePaletteINTERACTION | The ripple's colors, weak to strong, when rippleInk is palette. | 2 to 16 hex stops, comma separated | #c742dd, #ff6fd8, #ffd6f2, #ffffff |
rippleMoveScaleINTERACTION | The size of a ripple sent by a moving pointer, relative to the base ring. | 0.05 to 4 | 1 |
ripplePressScaleINTERACTION | The size of a ripple sent by a press, relative to the base ring. | 0.05 to 4 | 1 |
descriptionACCESSIBILITY AND CALLBACKS | The text alternative written onto the canvas for screen readers. | a sentence | a description of the turning form |
onFrameACCESSIBILITY AND CALLBACKS | Called after every drawn frame with the time in milliseconds and the playback position in seconds. Constructor only. | a function (nowMs, seconds) | none |
onStatusACCESSIBILITY AND CALLBACKS | The engine's one outbound channel: a line of text whenever something a host should know happens. Constructor only. | a function (message) | none |
Reduced motion is honoured by the engine on its own: one frame, no ripples.
getSourceFrame(maxSide = 640)Copies the current unprocessed image or media frame into a reused local canvas, capped at 1920 pixels. Returns null for procedural or unavailable sources. Does not acquire or control streams.update(options)Applies rendering settings in place. Set onFrame and onStatus callbacks in the constructor.setSource(fieldIdOrFunctionOrElement)A core built-in field id, custom luminance function, or image, video or canvas element you own. Workspace cafe-* field ids require the site's field functions; they are not core string ids.setImage(fileOrAddress)A File, a Blob or an address. Resolves true when it took and false with a status when not. Pictures up to 32 MB, scaled to 2048 px on the long edge.setVideo(fileOrAddress)The same for a clip the engine then owns, up to 512 MB.enableWebcam()Call it inside a click. Resolves true when the camera is live.enableScreenShare()The same for a window, a tab or a screen. screenShareSupport() says whether the browser can.setPlaying(on)Pauses or resumes playback.seek(seconds)Renders the frame at that time without changing the play state.snapshot(type?)The current frame as a data URL, PNG by default.toText()The frame as real characters, one line per row.destroy()Stops everything, releases the camera and the clip, removes what it added.Additional state and playback methods: getParams, getGrid, getSourceState, getSourceFit, mediaRate, restart, screenShareSupport. The color key set: eyedropperSupport, armEyedropper, disarmEyedropper, addKeyColor, getKeyState.
A settings file describes how to render a source. An ASCII capture contains the rendered character-level grids. They solve different problems.
Reapply the look to another source. Imported media is not embedded in a settings link. Match the settings version when reading JSON.
Keep grid dimensions, level rows, alphabet and colors. A player can scale the complete canvas without reducing its original density.
Request to feature records six seconds at up to 24 fps, reduced for dense grids. It uploads ASCII JSON and a cover with consent. Original files stay local. Show Original Background includes rendered source pixels as bounded JPEG frames; review them before consenting.
// Run after the source has loaded and onFrame has fired.
const frame = art.captureAscii({
mode: "frame",
text: true,
});
// Contains the rendered grid, ramp and level rows.
// This is different from a settings-only file.
const json = JSON.stringify(frame);The site’s feature player reapplies pointer effects to quantized levels. Ripple edges can differ from the live source, and a recorded loop may have a visible seam. Captured artwork is not the editable original media.
| Format | Free | Pro |
|---|---|---|
| PNG | Clean, up to 1080p | Clean, up to 4K |
| Text | Clean, current frame | Clean, current frame |
| GIF | Up to 6 s at 30 fps, up to 1080p, a small stamp bottom right | Up to 30 s, 60 fps up to 1080p and 30 fps at 4K, clean |
| MP4 | Not on the free plan | Up to 120 s, 60 fps up to 1080p and 30 fps at 4K, clean, where the browser can encode H.264 |
| Camera and screen | Live on the stage, clean stills | Clean GIF and MP4 recording at the canvas size |
| Settings link and settings file | Every plan | Every plan |
| Saved settings | One slot on this device | Several named looks |
Camera and screen recording uses the current canvas size. Resolution and frame rate depend on the source, browser and device. MP4 has an opaque background; use PNG or GIF for transparency.
Pro is $8 a month or $49 once for Lifetime Pro V1. Lifetime Pro V1 excludes major version upgrades.
How to build one.
https://ascii.cafe/app.54 of 54 entries
| Name | Purpose | Values | Default |
|---|---|---|---|
v | The link's schema version. Present whenever any other key is. A link omits every key at its default; a settings file and the save on this device write every key that applies, defaults included, and the same reader takes both. | 1 | absent on a bare link |
s | The moving field on the stage. | cafe-cup, orbit-sphere, cafe-donut, cafe-jellyfish, cafe-galaxy, cafe-terrain, cafe-bloom, cafe-vortex, drape, plasma, merge, converge, dispatch, sweep | none (the empty stage) |
t | The seed phrase a field is drawn from. The same phrase always draws the same motion. | 1 to 80 characters | a slow tide |
ex | A ready-made example: its source and its whole look. Any other key in the link lands on top of that look. A field example also writes s and t; a picture or video example is named by this key alone. | type-portrait, camera, paper-etching, prism-flow, coast-lines, photo-overlay, vinyl, moving-dots, terminal-donut, weather, jelly-glow, sweep, dispatch | none |
u | A public address the picture or video is fetched from, by the visitor's browser. | an http or https address, URL-encoded | none |
mk | The algorithm and line or text style. | g (Characters), d (Halftone), x (Dither), l (Engraving), f (Flow), t (Contour), w (Text Portrait) | g |
r | The alphabet, darkest character first. One character fills every cell and the colors carry the picture; a leading space leaves the darkest cells empty. | 1 to 16 characters, URL-encoded | ·K■| |
ld | Line direction | v (Vertical), h (Horizontal) | v |
txt | Repeating portrait text | 1 to 96 characters | stay curious keep looking |
lv | How many brightness levels the picture is cut into. | 2 to 16 | 5 |
cw | A ready-made colorway for the marks and the background. | mocha, pink, matcha, blue, white, snow, paper, ocean, latte, amber, terminal, rose, violet, mint, slate, lava, arcade, solar, voltage, signal, cobalt, citrus, sherbet, thermal, prism | white |
im | Foreground color mapping | t (brightness tones), g (spatial gradient) | t |
ia | Foreground gradient angle | 0 to 360 degrees; 90 runs left to right | 90 |
ink | A custom foreground color. Present instead of cw. | six hex digits, no # | the colorway's ink |
fa | The foreground's opacity, single ink only. | 10 to 100, steps of 5 | 100 |
bg | A custom background color. | six hex digits, no # | the colorway's ground |
pal | Tones: one color per brightness level, darkest first. Present instead of cw. | 2 to 16 six-digit hex stops, comma separated, no # | none |
cell | Density, as a multiplier on the cell size. Higher is finer. | 0.35 to 1.25, two decimals (the slider moves in steps of 0.05) | 0.62 |
c | Contrast. | 0.6 to 2, steps of 0.05 | 1.15 |
b | Brightness, applied before the levels are cut. | -0.5 to 0.5, steps of 0.01 | 0 for pictures and streams, -0.15 for fields, -0.12 for the empty stage |
dt | Dither, an ordered pattern between levels. | 0 to 1, steps of 0.05 | 0 |
inv | Invert: swap dark and bright. | 1 when on, 0 when off | off |
sp | Speed of a moving field or a video. | 0.25 to 3, steps of 0.05 | 1 |
pu | Pulse, a slow brightening and dimming of the whole picture. | 0 to 1, steps of 0.05 | 0 |
loop | Whether a video loops. | 0 when off, 1 when on | on |
an | A ready-made animation that runs on the stage and in GIF, MP4 and PNG files. One at a time. | breathe, jelly, beat, shake, wander, cycle, hues, aurora, split, shimmer, flicker, glow, scan, glitch, rain, cascade, contourwave, wave, spot, code, reveal, focus, type, wipe, center | none |
ai | How far the animation moves from your settings. Only with an. | 0 to 100, steps of 5 | 60 |
as | How fast the animation runs. Only with an. | 0.25 to 3, steps of 0.05 | 1 |
key | Source colors to remove from the selected layers (kr). | up to 16 six-digit hex values, comma separated, no # | none |
bk | Source colors removed from the original background independently of the effect | up to 16 six-digit hex values, comma separated, no # | none |
kc | Per-color effect tolerance overrides | JSON object mapping six-digit hex colors to values from 0 to 0.6 | none |
bc | Per-color original-background tolerance overrides | JSON object mapping six-digit hex colors to values from 0 to 0.6 | none |
bt | Tolerance for colors removed from the original background | 0 to 0.6, steps of 0.005 | 0.18 |
kt | How close a color has to be to a removed color to count. Only with key. | 0 to 0.6, steps of 0.005 | 0.18 |
see | See-through background: empty and removed cells are transparent in PNG and GIF files. | 1 when on, 0 when off | off |
asp | Cell aspect, the width of a cell relative to its height. | 0.5 to 1.6, steps of 0.05 | 1 |
cs | Canvas size in pixels. Auto follows the workspace; custom dimensions scale to fit the preview. Stage export uses the canvas size. | auto or WIDTHxHEIGHT, even integers from 64 to 3840, at most 8294400 pixels | auto |
mat | Mat inset, an empty margin around the picture in percent of the stage. | 0 to 14 | 0 |
fit | How a picture fills the stage: fill it, or match its width or its height. | c (Fill), w (Width), h (Height) | fill |
kr | Remove matching source colors from the effect, original background, or both | effect, background, both | effect |
ob | Show the original image or video behind the marks, using the same crop and fit | 0 or 1 | 0 |
bo | Opacity of the background color or gradient, independent of the marks | 0 to 1, steps of 0.01 | 1 |
oa | Original background opacity over the solid or gradient background | 0 to 1, steps of 0.01 | 1 |
bm | Background mode | solid, linear, radial | solid |
bp | Background gradient stops, evenly spaced | 2 to 5 comma-separated six-digit hex colors | 101828,312e81 |
ba | Linear background angle, clockwise from up | 0 to 360 degrees | 90 |
fps | Cadence: how many times a second the stage redraws. | 4 to 60 | 16 |
dv | Halftone only: brighter cells draw a brighter disc as well as a bigger one. | 1 when on, 0 when off | off |
halo | Cursor halo, the brightening under the pointer. | 0 when off, 1 when on | on |
hr | How far the halo reaches from the pointer. | 0.05 to 0.8, steps of 0.01 | 0.05 |
rip | Click ripples. | 0 when off, 1 when on | on |
rc | The ripple's own color instead of the colorway's stops. | six hex digits, no # | the colorway's ripple stops |
rs | Click ripple size, relative to the base ring. | 0.05 to 4, steps of 0.05 | 1.5 |
rp | Custom ripple colors, weak to strong. | 2 to 5 six-digit hex stops, comma separated, no # | the colorway ripple stops |
A look for the visitor's own picture: halftone, eight levels, Amber. Drop a picture on it.
https://ascii.cafe/app?v=1&mk=d&lv=8&cw=amberAn example with a look: the Weather example, the Classic alphabet, ten levels, Terminal.
https://ascii.cafe/app?v=1&ex=weather&s=plasma&t=rain+on+tin&r=+.%3A-%3D%2B*%23%25%40&lv=10&cw=terminalTemplate for a public picture with tones and a see-through background. Replace https://example.com/photo.jpg with your own image URL that allows cross-origin access.
https://ascii.cafe/app?v=1&u=https%3A%2F%2Fexample.com%2Fphoto.jpg&pal=1f5c47,4fc39a,d9fff0&see=1A link reproduces the look. The picture stays with whoever made it, unless it is a public address.
Check the container height, wait for the source to finish loading, and inspect getSourceState(). A remote URL also needs appropriate CORS headers.
Use HTTPS or localhost and call the permission method directly from a user click. A previous permission does not let a link restart a capture session.
Use sourceFit: width or height to keep that dimension visible. Cover fills the available area and can crop the other dimension.
Density is a column count in the engine. Increase it for a finer live grid. For captured ASCII, preserve the stored grid and scale the canvas rather than rebuilding a smaller grid.
The workspace checks browser H.264 encoding support. Use GIF when MP4 encoding is not available.
Create one instance after mount, update it in place, and call destroy() from the effect cleanup. Avoid constructing an engine during render.
The engine that draws this page, as one file you can ship: no dependencies, no server and no attribution required. One license applied to a single website or project.
Pro plans cover what the workspace exports; the developer license covers shipping the engine itself.
GET THE LICENSE →