Skip to main content

find-itch-games (Python)

Find the itch.io app, its install locations, and the games installed in them.

See the root README for how itch stores its data, where it installs games, and the shared definitions both language implementations are built against. This page covers the Python API.

Install

pip install find-itch-games

Requires Python 3.10 or newer. No runtime dependencies — sqlite3, gzip and json are all in the standard library. Unlike the JavaScript package, whose floor is set by node:sqlite, there is no version constraint beyond Python itself.

Usage

import find_itch_games as fig

fig.find_itch_path()
# => PosixPath('/home/you/.config/itch')

fig.find_itch_libraries_paths()
# => [PosixPath('/home/you/.config/itch/apps'),   # the built-in `appdata` location
#     PosixPath('/home/you/Games')]               # one the user added

fig.find_itch_app_by_id(4225297)
# => PosixPath('/home/you/Games/distributrains')

fig.find_itch_app_by_name("Distributrains")
# => PosixPath('/home/you/Games/distributrains')
# the game's title, its url slug ("distributrains") and its install folder
# name all work

fig.has_itch_app(4225297)
# => True

Everything returns pathlib.Path, and the API is synchronous — unlike the JavaScript package, which is async because Node's filesystem API is.

Looking games up by name

By default a name must match the title, url slug or install folder name exactly. Pass exact=False for a search that ignores case, spacing and punctuation:

fig.find_itch_app_by_name("Cosmic Collapse, a suika-like")    # exact title
fig.find_itch_app_by_name("cosmic-collapse")                  # exact slug
fig.find_itch_app_by_name("cosmic collapse", exact=False)     # fuzzy

A fuzzy search can match similarly named games, and the same game can be installed in two locations. Use the plural forms to see every match, or strict=True to fail rather than guess:

fig.find_itch_apps_by_name("reboot", exact=False)   # -> list[App]
fig.find_itch_apps_by_id(4225297)                   # every install of that game

fig.find_itch_app_by_name("reboot", exact=False)                 # first match
fig.find_itch_app_by_name("reboot", exact=False, strict=True)    # raises AmbiguousAppError

find_itch()

The whole picture in one call:

itch = fig.find_itch()
# Libraries(
#   itch_path=PosixPath('/home/you/.config/itch'),
#   database_path=PosixPath('/home/you/.config/itch/db/butler.db'),
#   database_available=True,
#   strategy='merge',
#   libraries=[
#     Library(id='appdata', path=..., is_default=False, exists=True, source='db', apps=[]),
#     Library(id='87c69020-…', path=PosixPath('/home/you/Games'), is_default=True,
#             exists=True, source='db',
#             apps=[App(game_id=4225297, path=..., manifest=AppManifest(...))]),
#   ])

find_itch_app_manifest(game_id)

The itch answer to Steam's appmanifest_*.acf: the cave row and the receipt, merged and flattened into an AppManifest dataclass.

manifest = fig.find_itch_app_manifest(1323129)
manifest.title          # 'Godot PCK Explorer'
manifest.slug           # 'godot-pck-explorer'
manifest.author         # 'dmitriysalnikov'
manifest.version        # '1.6.0'
manifest.channel_name   # 'native-console-linux-64'
manifest.installed_size # 15783510
manifest.source         # 'db+receipt'

fig.get_launch_candidate_paths(manifest)
# => [PosixPath('/home/you/Games/godot-pck-explorer/GodotPCKExplorer.Console')]

candidates is butler's own scan of the folder, so it is how you find the binary to run without guessing. It is empty for games butler has not configured yet.

Options

Every entry point takes the same keyword arguments.

Option Default Meaning
itch_path auto-detected Use this itch user-data directory instead of searching.
strategy "merge" Which of itch's records to read — see below.
check_exists True Drop games whose install folder no longer exists.
extra_libraries None Additional install locations to scan.
ignore_database False Never open butler.db, not even for install locations.
lookup None A PathLookup — search as another user, environment or OS.

The lookup functions take two more: exact (name lookups only) and strict.

Strategies

  • merge — read butler.db, confirm each game against the receipt in its install folder, then add any receipt with no matching row. Most complete.
  • db — read butler.db only. Fastest, and the only source of play times, launch candidates and custom install folders.
  • receipts — ignore the caves table and scan the install locations. Useful when the database is stale. Install locations still come from the database, since nothing on disk records them.

manifest.source tells you which record each result came from: "db", "receipt" or "db+receipt". The valid strategies are exported as ITCH_STRATEGIES; anything else raises ValueError rather than being silently treated as merge.

Searching as another user

PathLookup overrides the home directory, environment and platform the search is based on — for scanning several user profiles, or a mounted disk:

from find_itch_games import PathLookup, get_itch_path_candidates

get_itch_path_candidates(PathLookup(
    home="/mnt/disk/Users/someone",
    env={"APPDATA": "/mnt/disk/Users/someone/AppData/Roaming"},
    platform="win32",
))

fig.find_itch(lookup=PathLookup(home="/mnt/disk/Users/someone"))

Each field defaults to Path.home(), os.environ and sys.platform.

Errors

  • ItchNotFoundError — no itch user-data directory found.
  • AppNotFoundError — raised by find_itch_app_by_id / find_itch_app_by_name.
  • AmbiguousAppError — several games matched and strict=True; .paths lists them.
  • ItchDatabaseErrorbutler.db exists but cannot be read.
  • ValueErrorstrategy was not one of ITCH_STRATEGIES.

Development

pip install -e ".[dev]"
python -m pytest

The tests build the shared installation described by shared/fixtures.json, using the schema in shared/butler-schema.sql, and assert against the vocabulary in shared/definitions.json — the same three files the JavaScript suite uses.

tests/test_parity.py additionally runs both implementations against the real itch installation on the machine and compares their output. It skips itself when itch is not installed, or when the JavaScript package has not been built.

Building and publishing use hatchling:

python -m build            # sdist + wheel into dist/
pipx run twine check dist/*

The version is single-sourced from __version__ in src/find_itch_games/__init__.py, and is kept in lockstep with the JavaScript package by npm run version:sync in node/. Because Python was added after the first JavaScript release, PyPI has no 0.1.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

find_itch_games-0.1.1.tar.gz (21.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

find_itch_games-0.1.1-py3-none-any.whl (26.2 kB view details)

Uploaded Python 3

File details

Details for the file find_itch_games-0.1.1.tar.gz.

File metadata

  • Download URL: find_itch_games-0.1.1.tar.gz
  • Upload date:
  • Size: 21.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for find_itch_games-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a091c92d4f7ce71548674868a64eb9e98b32fe4c003bef6dd9a32de8e3da09e8
MD5 d692259ba328cd85e33a843c1e8ab887
BLAKE2b-256 f61c5966859bca79cb89775e56093e2101064a808cb420ed8da6269ed635de78

See more details on using hashes here.

File details

Details for the file find_itch_games-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for find_itch_games-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cc94bbbf43453e66bf1e02f9bf992b8fddd6d3ddb17cdd3b81c05b1a936163ae
MD5 f834b4bc5139acfc4f4de64e1774b00d
BLAKE2b-256 cc4919ced5ffac41d52900b77f819255cec98f20421be698bba593922aa27cc3

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page