# Art: a 700-font ASCII art library for Python

> A dependency-free Python package holding 677 fonts, 711 one-line arts and 218 decorations, with a packaging file that disagrees with its own release notes about which Python versions it supports.

**sepandhaghighi/art** — 🎨 ASCII art library for Python

- Repository: https://github.com/sepandhaghighi/art
- Website: https://www.ascii-art.site
- Stars: 2,506 · Forks: 162
- Language: Python
- License: MIT
- Published: 2026-10-08 · Updated: 2026-10-08 · Language: en
- Canonical page: https://hysenlabs.com/projects/sepandhaghighi-art

## Three functions and a large pile of data files

The public surface is small enough to learn in a minute. art returns a one-line picture as a string, aprint prints one instead of returning it, and randart picks one at random. text2art is the one that matters most in practice, because it renders a string in one of 677 fonts. Each of those three functions raises artError rather than returning a placeholder when it gets the wrong argument type, which is a better failure mode than silently printing nothing.

```pycon
>>> from art import *
>>> art_1=art("coffee") # return art as str in normal mode
>>> print(art_1)
>>> art_2=art("woman",number=2) # return multiple art as str
```

The volume is in the data rather than the code. The README's counters and its badges agree on the current totals: 677 fonts, 711 one-line arts and 218 decorations. Those badges point at three Jupyter notebooks in the repository root, FontList.ipynb, ArtList.ipynb and DecorList.ipynb, so the catalogue is browsable before you install anything. The library also exposes the name lists programmatically: ART_NAMES arrived in version 4.2, NON_ASCII_ARTS in 4.6, and ASCII_ARTS in 5.7 for when you specifically need the entries that survive a plain ASCII pipeline.

What that last point leads to is the library's real constraint, which the README states twice and in slightly different words. Some one-line arts do not render in every environment, and some fonts do not cover every character. If you are printing to a terminal that cannot handle the combining marks and geometric characters these arts rely on, the failure is on the display side rather than in the library, and no amount of code in your process will change it.

## setup.py and the v6.5 release note contradict each other

Here is a conflict worth looking at directly rather than resolving by assumption. The packaging file declares a floor of Python 3.6:

```python
python_requires='>=3.6',
```

The v6.5 release notes, published 12 April 2025, list under Changed: Python 3.6 support dropped. Both statements describe the same version of the project, because setup.py carries version='6.5' in the same file as that python_requires line. One of them is out of date, and there is no way to tell from the repository which the maintainer intends.

The practical consequence is narrow but real. A project that reads python_requires as authoritative will happily resolve art on Python 3.6, and if the interpreter really has dropped that version then some part of the code will fail at runtime rather than at install time. Choosing 3.7 or newer removes the ambiguity without costing you anything the library offers.

This is also a good example of why the setup.py in a single-file-era package deserves reading even when the PyPI page looks fine. The rest of that file is informative. install_requires is an empty list, so the library has no runtime dependencies at all. packages lists art, art.data and art.tests, meaning test modules are shipped inside the installed distribution rather than kept out of it. The long description is assembled at build time by concatenating README.md and CHANGELOG.md, with a hardcoded MINIMAL_DESCRIPTION used as a fallback if either file cannot be read. That fallback existing at all tells you the build has been run in environments where those files were absent.

## The newest tag is a year and a half behind the last push

The repository's last push is dated 21 September 2026. Its newest release tag is v6.5, published 12 April 2025. That gap is the second fact worth holding onto, because it changes what installing from PyPI gets you compared to what browsing the repository shows.

The three published releases read as a fairly conventional progression. v6.3 in September 2024 was a structural release: it added the data and tests directories, split the art module into errors, utils and functions, renamed art_param to params, and renamed the three font dictionaries to fonts1, fonts2 and fonts3. Ten new fonts arrived in the same release, including names like lolie, zakia and lord_of_the_ring.

v6.4 in November 2024 added the line and lprint functions and five more fonts, and also added Python 3.13 to the test workflow. v6.5 added one art and five fonts, dropped Python 3.6, and modified the test system. Every release since 6.3 is additive to the catalogue and modest in structural terms, which is the profile of a stable library rather than one being reshaped.

So if you need a font added after v6.5, you are looking at code that has no tag. The fonts are data files, so the risk of that code is low, but the version number you will report in a bug report will not match anything anybody else can install. Note also that the default branch is master rather than main, and the v6.4 notes mention that GitHub actions are limited to the dev and master branches. A project with a dev branch and 677 data files is one where the interesting question is usually how unreleased the unreleased part is.

## Text rendering has accumulated four compatibility rules

text2art looks like a one-liner and behaves like a compatibility negotiation. Four rules have accumulated across versions, and each one is documented as a warning rather than as an option you set.

The first is character coverage. Not every font supports every character, so a font that renders Latin text perfectly will do something unspecified when handed Cyrillic or an emoji. The second is encoding of the fonts themselves: non-ASCII fonts were added in version 3.3, and the README is explicit that they are not compatible with some environments. If your output has to survive a mail client or an old log viewer, restrict yourself to the ASCII_ARTS list rather than filtering by name.

The third rule concerns line endings and it is the one most likely to bite you. From version 5.3 the default separator is a newline rather than a carriage return plus newline. Code written against art before 5.3 that assumed \r\n will now produce output with different line lengths, which matters if you are padding art to a fixed width or slicing it by column. The sep parameter overrides the choice.

The fourth is a removal rather than an addition. Version 4.6 is the last release supporting Bipartite art, so a name that worked in an older version can now fail. The art function's own signature has stayed stable while these rules moved underneath it, which is exactly the situation where a version pin in your requirements file earns its keep.

## A MATLAB directory, notebooks, and two autopep8 scripts

The repository tree explains more about how this project is maintained than the README does. Alongside the art package there is a MATLAB directory, which is an unusual thing to find in a Python-only ASCII art library and suggests an interest in reaching the same catalogue from a second language. Nothing in the README's usage section mentions it, so treat it as an adjacent experiment rather than a documented feature.

There are three notebooks at the root, one per catalogue, and they are the project's real user interface. FontList.ipynb is the one to open first. Rendering a font to compare two candidates interactively is a better workflow than reading a list of 677 names and guessing.

Then there are autopep8.sh and autopep8.bat sitting next to art_profile.py at the repository root. Two launcher scripts for the same formatter, one for POSIX shells and one for Windows, tell you that contributors arrive from both platforms and that the maintainer keeps formatting helpers at the top level rather than in a task runner. dev-requirements.txt holds the development dependencies and codecov.yml drives coverage reporting, and the README carries Codecov, Codacy, CodeFactor and Codebeat badges, which is a lot of automated quality checking for a library whose main content is text art. Coverage is meaningful here, incidentally, because the interesting logic is name lookup and fallback rather than anything numerically involved.

One naming caution deserves a mention. The distribution is called art, one letter and a word that many unrelated packages also want. If you are adding it to a project that already has a local module or a transitive dependency with that name, check what actually gets imported before assuming art() came from this library.

## Conclusion

Art earns its place for the narrow job of turning a string or a name into something decorative, and it does that with zero runtime dependencies, which is rarer than it should be for a library shipping 677 fonts. Two things deserve a decision from you rather than an assumption. First, the Python floor is genuinely ambiguous: setup.py says 3.6 while the v6.5 notes announce that 3.6 support was dropped, so pin your interpreter to 3.7 or newer rather than trusting the metadata. Second, the newest tagged release is v6.5 from April 2025 while the repository has been pushed to since, so if you need the fonts added after that tag, install from the branch and accept that you are tracking unreleased code. Start at text2art for banners and art for one-line pictures, then read FontList.ipynb before assuming a particular font supports the characters you plan to pass it.

## FAQ

### How do I render text in an ASCII font with Python?

Call text2art with your string, for example text2art("art"), and it returns the rendered block as a string with a default font and chr_ignore=True. Pass font= to choose one of the 677 fonts, and note that not every font supports every character.

### Does the art library install any dependencies?

No. The packaging file lists an empty install_requires, so art adds nothing to your dependency graph. Development dependencies are separate and live behind the dev extra.

### Which Python versions does art support?

The repository is ambiguous on this. setup.py declares python_requires of 3.6 or higher while the v6.5 release notes list Python 3.6 support as dropped, and both describe the same release. Targeting 3.7 or newer avoids having to guess which statement the maintainer intends.

### How do I pick a font before committing to one?

Open FontList.ipynb in the repository, which renders the catalogue interactively, or read ART_NAMES after installing to get the full list programmatically. ASCII_ARTS narrows that list to entries that stay within plain ASCII.

## Sources

- [License: MIT](https://github.com/sepandhaghighi/art/blob/master/LICENSE)
- [Project website](https://www.ascii-art.site)
- [README](https://github.com/sepandhaghighi/art/blob/master/README.md)
- [Releases](https://github.com/sepandhaghighi/art/releases)
- [sepandhaghighi/art on GitHub](https://github.com/sepandhaghighi/art)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sepandhaghighi-art
