pyahocorasick, a C extension that searches for many strings in one pass
Python module (C extension and plain python) implementing Aho-Corasick algorithm
At a glance
- What is it?
- pyahocorasick is a Python module implementing the Aho-Corasick algorithm, which finds every occurrence of many key strings in an input in a single pass. The Automaton class doubles as a plain trie before it is finalized, the index can be pickled to disk and reloaded, and the build is compiled either for Unicode or for bytes depending on an environment variable.
- Who is it for?
- Adopt pyahocorasick if you need to look for a large fixed set of strings in a stream of text and you want it to be fast without leaving Python, keeping in mind that the search structure is built ahead of time and reused.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 179 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One pass, many needles
The library is described as a fast and memory efficient library for exact or approximate multi-pattern string search, meaning you can find multiple key string occurrences at once in some input text. The metaphor is the standard one, a haystack and needles, and the algorithm is the Aho-Corasick automaton, which lets you search all occurrences of multiple strings in an input string making a single pass over the input. The stated advantage is in the runtime guarantees rather than in a peak number: the typical worst-case and best-case runtimes are about the same, depending primarily on the size of the input string and secondarily on the number of matches returned. The project is candid that this may not be the fastest string search algorithm in all cases, but the ability to search for many strings at once combined with those runtime guarantees is what makes it distinct. The classic use case named is fast multi-pattern matching in intrusion detection systems such as snort, anti-viruses and other systems that match against a pre-defined set of string keys.
making a single pass over the input stringThe Automaton is a trie first and an automaton second
The library exposes two data structures through one class, and the order of operations matters. The Automaton is a Trie, a dict-like structure indexed by string keys each associated with a value object, and you can use it to retrieve a value in a time proportional to the string key length. You add keys with their values, you can test membership, and you can fetch a value with a dict-like get method that raises a KeyError for a missing key unless you supply a default. Then you call make_automaton to convert the trie into a searching automaton, and only after that can you run the search. The drawback the documentation names is that the structure must be constructed and finalized ahead of time before you can search strings, and the response is that in several applications where you search for several pre-defined needles in a variable haystack this is actually an advantage. The evidence for that claim is in the way the library is used in the wild, and the project keeps a wiki page on who is using it.
>>> import ahocorasick
>>> automaton = ahocorasick.Automaton()
>>> for idx, key in enumerate('he her hers she'.split()):
... automaton.add_word(key, (idx, key))
>>> automaton.make_automaton()Iterating the matches, and the index you can pickle
Searching returns results through an iter method that yields two-tuples of the end index where a trie key was found and the associated value for that key, and the example in the documentation uses the fact that the value stored was a tuple of the original string and its insertion order. The example then reconstructs the start index from the end index and the length of the matched value, and asserts that the slice of the haystack matches the original, which is a nice touch because it verifies the offsets rather than just printing them. The second capability is persistence: you can create an eventually large automaton ahead of time and pickle it to reload later, and the example pickles to a string where you would typically pickle to a file. This is the feature that turns the library from a runtime structure into a build artefact, and it is what the description means when it says the strings index can be built ahead of time and saved as a pickle to disk to reload and reuse later.
>>> import pickle
>>> pickled = pickle.dumps(automaton)
>>> B = pickle.loads(pickled)
>>> B.get('he')
(0, 'he')Two builds, and the environment variable that picks one
The build script is where the library's one real decision surfaces. The extension is compiled from a single source file with a set of C headers for the trie, the automaton, the search iterators and the pickling support, and a define macro selects the string model. The setup checks two environment variables, one for building as bytes and one for building as unicode, and raises an exception if both are set, with the message that only one should be set. When neither is set, unicode is the default. The Makefile mirrors that choice with a unicode build target and a bytes build target, each of which removes the previous build artefacts and does an editable install into a local virtual environment, and the test targets follow the same pattern, installing the testing extra and running pytest verbosely. The two flavours are not interchangeable, and the build will not let you have both in one extension.
AHOCORASICK_UNICODE=yes venv/bin/pip install -e .Two flavours of module, and what the pure Python one costs
The library ships in two forms and the difference is not only speed. The primary one is a CPython C-based extension, compatible with Python 3 only, and the documentation points at the older 1.4.x version for Python 2.7 and 32 bit support. The second is a simpler pure Python module, compatible with both Python 2 and 3, which is only available in the source repository and not on PyPI, under the etc/py/ directory, and which has a slightly different API. The extension is written in C and tested on Python 3.9 and up, and it works on 64 bit Linux, macOS and Windows. That last point has a consequence: on a 32 bit system you are back to the old 1.4.x line. The pure Python variant matters for anyone who cannot compile a native extension, and the documentation is upfront that the API is not identical there.
* a simpler pure Python module, compatible with Python 2 and 3.The engineering around it, and the licence
The repository shows the discipline behind the library. There is a valgrind target that runs the test suite under a full leak check with origin tracking, writing to a log file, which is the kind of thing a memory safety conscious C project does. There is a benchmark target pointing at a script under the benchmarks directory, and a test runner script at the root. The virtual environment for development is bootstrapped by downloading the virtualenv zip from the bootstrap site rather than assuming it is present, which keeps the build reproducible on a machine with nothing but Python. The licence is BSD-3-Clause, and the documentation notes that some utilities, such as the tests and the pure Python automaton, are dedicated to the Public Domain. The primary language recorded for the repository is C. The release history shows steady work, with v2.3.1 in April 2026, v2.3.0 in December 2025 and v2.2.0 in June 2025, and the last push was on 2026-04-27.
valgrind:
venv/bin/python3 -c "import sys;print(sys.version)"
valgrind --leak-check=full --track-origins=yes --log-file=valgrind.log venv/bin/pytest -vvsWhere it fits, and what to check first
The scope is matching a known set of strings, and that is a real niche with real users. The testimonial in the documentation is a good illustration: a library of a hundred thousand plus CRISPR guides counted in a stream of millions of DNA sequencing reads, where the package did it faster than the previous C program and let the team stick to just Python in the pipeline. That is the shape of the use case, a large fixed vocabulary applied repeatedly to a stream. The three checks before you build on it are mechanical. Can you compile a C extension, or do you need the pure Python variant from the source repository, which is not on PyPI and has a slightly different API. Do you want Unicode or bytes, since the build is one or the other and the setup raises if you ask for both. And do you have a place to keep the pickled automaton, because the whole performance argument rests on building the index once and reusing it, and building it per request is slower than not using the library at all. The library is BSD-3-Clause licensed.
BSD-3-ClauseEditorial conclusion
Adopt pyahocorasick if you need to look for a large fixed set of strings in a stream of text and you want it to be fast without leaving Python, keeping in mind that the search structure is built ahead of time and reused. Verify three things before you commit: whether you can build the extension, since the module is written in C and needs a compiler, with a pure Python variant available in the source repository if you cannot; whether you need Unicode or bytes semantics, since the build is one or the other and the setup refuses to produce both; and the memory cost of the index, because a large automaton is built once and then reused, and building it per request defeats the purpose.
Frequently asked questions
What does the pyahocorasick library do?
It is a fast and memory efficient library for exact or approximate multi-pattern string search, so you can find multiple key string occurrences at once in an input text. The index can be built ahead of time and saved as a pickle to disk to reload and reuse later, and it provides an ahocorasick module usable as a plain dict-like Trie or convertible to an automaton for efficient Aho-Corasick search.
How do I install and use pyahocorasick?
The module is written in C so you need a C compiler to compile the native extension, and you install it with `pip install pyahocorasick`. You create an Automaton, add your keys and values with add_word, call make_automaton to convert the trie into a searching automaton, and then use the iter method to walk the matches over your input string.
What is the difference between the C extension and the pure Python module?
The C-based extension is compatible with Python 3 only, and the older 1.4.x version covers Python 2.7 and 32 bit support. The simpler pure Python module is compatible with Python 2 and 3, is only available in the source repository and not on PyPI under the etc/py/ directory, and has a slightly different API.
Can I persist a pyahocorasick index?
Yes. You can create an eventually large automaton ahead of time and pickle it to reload later, pickling to a string in the example but typically to a file. The reconstructed object supports the same dict-like access, so a pickled automaton can be loaded and queried directly.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wojciechmula-pyahocorasick)Was this useful?