Library / SDK
guessit-io/guessit avatar
guessit-io/guessit

guessit: pulling title, season, codec and release group out of a video filename

GuessIt is a python library that extracts as much information as possible from a video filename.

944 stars107 forksPythonLGPL-3.0

At a glance

What is it?
GuessIt is a Python library that parses video filenames and returns a structured dict of properties, covering movies and TV episodes alike, built on the Rebulk pattern engine. It is aimed at anyone with a directory of downloaded or ripped media filenames that need to become database rows.
Who is it for?
GuessIt fits media indexers, renamers and anything that needs to turn messy filenames into structured rows, and it does not fit a workflow that needs to read the file contents, because the library works from the filename alone.
Can I use it commercially?
Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is a filename, not a video file

GuessIt is described as a library that extracts as much information as possible from a video filename, and it works with both movies and TV show episodes. The input is a string such as a scene release name with title, season and episode numbers, quality markers, codec and a trailing group tag all run together. The output is a dictionary of properties. The stated use case is anything that has to make sense of a large collection of such names: a media indexer, a renaming script, a catalogue importer. The library itself does not open the video, does not read metadata from the container and does not talk to a database. It is a text parser with a large rule set, and that boundary is the single most important thing to understand before choosing it. The documentation points to the API and options reference for the full surface, and the full documentation site is guessit-io.github.io/guessit.

Rebulk does the pattern matching underneath

The architecture is a thin layer over another project. The documentation states that GuessIt relies on Rebulk for pattern and rules registration, and pyproject.toml pins rebulk>=6.0.1,<7 as the first dependency, alongside babelfish>=0.6.1 and python-dateutil>=2.8.0. That dependency choice explains a lot about the behaviour. Because patterns are registered as rules rather than hand-written parsers, the same token can be matched with different expectations depending on position, and a filename pattern such as 1x03 is recognised as a season and episode pair rather than as two numbers. The babelfish dependency is another building block, and country codes such as US do appear in the results, as the Shameless example below shows. There is an optional extra named regex that pulls in the regex package, so the standard library behaviour and the extended behaviour are separate and optional.

MatchesDict preserves order, which matters when titles are ambiguous

The library API returns an ordered MatchesDict of the detected properties, and the examples show it printing as a plain dict-like object. The ordering is not cosmetic. Filenames put the informative part in different places depending on the release style, so a matcher has to decide which candidate is the title, and that decision depends on what has been matched already. An anime style name leads with a bracketed group, a scene style name ends with a hyphenated group, and a title containing digits or a year can be mistaken for an episode number. The order in which properties are matched is the order in which ambiguity is resolved. The documented examples show this at work: Shameless.US.S05E10.720p.HDTV.x264-KILLERS.mkv resolves to a title of Shameless, a country of US, season 5 and episode 10, while [Anime-Group] Attack on Titan - 25 resolves to a release group of Anime-Group and episode 25 with no season key at all, since the name carries no season information.

A first run from the command line and from Python

The project ships a console entry point, declared in pyproject.toml as guessit = guessit.__main__:main, and the documentation shows it used on a sample release name.

shell
guessit "Treme.1x03.Right.Place,.Wrong.Time.HDTV.XviD-NoTV.avi"

Running that prints the properties found, including the episode_title Right Place, Wrong Time, the source HDTV, the video_codec Xvid, the release_group NoTV, the container avi and the mimetype video/x-msvideo, with type set to episode. From Python the call is a single function returning that same structure.

python
from guessit import guessit

guessit('The.Matrix.1999.1080p.BluRay.x264-GROUP.mkv')

The result carries a title of The Matrix, a year of 1999, a screen_size of 1080p, a source of Blu-ray, a video_codec of H.264, a release_group of GROUP, a container of mkv, a mimetype of video/matroska and a type of movie. Note that the codec is normalised on the way out, so x264 in the filename becomes H.264 in the result, and the container gets a mimetype derived from it.

Python 3.10 and up, with a locked uv environment in the container image

The packaging metadata is modern and strict. pyproject.toml names the project guessit at version 4.4.0, requires-python >=3.10, and the classifier list covers Python 3.10 through 3.14, marked as Production/Stable and OS Independent. The development status classifier and the semantic-release badge indicate a project that ships versions automatically, and the recent release history backs that up: v4.2.1 and v4.3.0 on 2026-07-30 and v4.4.0 on 2026-07-31. The Dockerfile takes a different route to reproducibility, building on python:3.13-alpine and copying the uv binary in from ghcr.io/astral-sh/uv:latest.

dockerfile
RUN uv sync --locked --no-default-groups

ENTRYPOINT ["uv", "run", "guessit"]

The uv sync --locked step installs exactly what uv.lock pins, and the entrypoint runs the installed console script rather than the source tree. The top level of the repository also carries tox.ini, uv.lock, a .pre-commit-config.yaml and a Dockerfile, alongside scripts/ and docs/ directories, so the supported way to work on the project is dependency-locked from the start.

Where filename parsing stops working

There is a clear failure mode, and it is not a bug in the matcher. GuessIt sees a string and nothing else, so anything not encoded in the filename cannot be recovered. A file called episode01.mkv yields a very short dict, because there is no title, no season marker and no group. Rename a file to something clean and you lose the release group, the source and the codec that the original name carried. The library does not read sidecar metadata, and the documentation does not describe any way to merge results with information from a container or a media server catalogue.

guessit-js exists, and the licence difference matters more than the language

For a JavaScript or TypeScript project, the documentation points to guessit-js, a third-party TypeScript and WASM port maintained by OpenSubtitles that runs in Node, in browsers and in WASM with no Python required. The documentation is careful to say it is not affiliated with this project, so behaviour between the two can differ and you should not assume feature parity. GuessIt is licensed under LGPLv3, and pyproject.toml states the licence as LGPL-3.0-or-later. The LGPL is a weak copyleft licence: using the library as an unmodified dependency in your own product is generally not the same commitment as vendoring a modified copy, and the obligations attach differently. This is not legal advice, so read the LICENSE file before you ship anything, but it is a different kind of constraint from the permissive licences common in the Python ecosystem, and worth checking before you adopt the library.

Editorial conclusion

GuessIt fits media indexers, renamers and anything that needs to turn messy filenames into structured rows, and it does not fit a workflow that needs to read the file contents, because the library works from the filename alone. Before adopting it, check the Python requirement, since pyproject.toml asks for 3.10 or newer, and note that the project is licensed LGPL-3.0-or-later, so a modified version distributed as part of a larger product carries obligations the MIT-licensed alternatives do not.

Frequently asked questions

What does guessit return for a movie filename?

It returns a MatchesDict of detected properties. For The.Matrix.1999.1080p.BluRay.x264-GROUP.mkv the documentation shows a title of The Matrix, a year of 1999, a screen_size of 1080p, a source of Blu-ray, a video_codec of H.264, a release_group of GROUP, a container of mkv, a mimetype of video/matroska and a type of movie.

How do I call guessit from Python?

Import the guessit function and pass the filename as a string, for example from guessit import guessit followed by guessit('Shameless.US.S05E10.720p.HDTV.x264-KILLERS.mkv'). The result is an ordered MatchesDict, and the API and options reference documents the full surface.

Can guessit be used without Python?

The documentation points to guessit-js, a third-party TypeScript and WASM port maintained by OpenSubtitles that runs in Node, in browsers and in WASM with no Python required. It is not affiliated with the GuessIt project, so the two are not guaranteed to behave identically.

Official sources

  1. guessit-io/guessit on GitHub
  2. License: LGPL-3.0
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/guessit-io-guessit.svg)](https://hysenlabs.com/projects/guessit-io-guessit)

Was this useful?