It's here, it's real and it's awesome: 4.0.0 is our most feature-packed release yet! 💫
We're thrilled to finally announce the long-awaited hash-based metadata matching feature, which allows you to validate your ROMs against popular DATfile databases like No-Intro, Redump and TOSEC.
Caution
This release fixes a critical authenticated arbitrary file write vulnerability (CVE-2025-54071) in all API endpoints that accept uploaded files, which can lead to remote code execution on the system. All previous versions are affected. All users should update immediately to this version, or see the mitigations in the advisory below. #2085
GHSA-fgxf-hggc-qqmq
Highlights
Hash-based metadata matching
We've partnered with two friends and members of the community, @michael-j-green and @DevYukine, to bring you a powerful new feature that allows you to match your ROMs against hash databases like No-Intro, Redump and TOSEC. They've built new public and free APIs, Hasheous and Playmatch respectively, that validate the contents of your ROM files against these databases. In the case of Hasheous, it also proxies metadata from IGDB, so you no longer need to set up IGDB credentials to fetch metadata from IGDB.
To start using Hasheous, simply set HASHEOUS_API_ENABLED=true
in your environment variables, and future scans will use the Hasheous API. And for Playmatch, set PLAYMATCH_API_ENABLED=true
in your environment variables. Note that you'll need to set up IGDB credentials to use Playmatch, as it does not proxy IGDB metadata like Hasheous does.
You can find popular metadata provider combinations for scans in the documentation.

LaunchBox metadata
The LaunchBox Games Database is a community-driven database that provides metadata, cover art, and screenshots. Like the LaunchBox desktop application, RomM downloads the entire database locally and matches games based on their exact filenames. This is a privacy-friendly option for users who want to import metadata without relying on online APIs, and/or already use LaunchBox to manage their game collections.
To enable LaunchBox, set LAUNCHBOX_API_ENABLED=true
in your environment variables. You can enable regular updates of the database by setting ENABLE_SCHEDULED_UPDATE_LAUNCHBOX_METADATA
, and set the frequency of the cron job with SCHEDULED_UPDATE_LAUNCHBOX_METADATA_CRON
(defaults to 5:00 AM every day).
SteamGridDB during scans
SteamGridDB, the community-driven platform for cover art, is now available to use during scans. When selected as a source on the scan page, RomM will prioritize high-quality cover art from SteamGridDB for both matched and unmatched (no metadata found) games. Instructions for setting up SteamGridDB are available in the documentation.

Mark games with missing files as "missing"
In previous versions, RomM would delete games from the database if the file(s) were missing from the filesystem. This would lead to the loss of notes, save files and manual metadata matches. Now, these games will be marked as "missing" instead of being deleted, allowing you to restore them later if the files are added back. Use the filter bar on the search, platform and collection pages to easily find these games.
Android app
Community member and developer extraordinaire @mattsays has just released an unofficial companion app for RomM. The app allows you to browse, manage, and organize your retro gaming collection directly from your Android device, as well as download games to it. While the app is not yet available on the Google Play Store, you can download the latest APK from the GitHub repository.
DOS with EmulatorJS
Playing MS-DOS games in the browser is now possible with EmulatorJS, with a bit of setup required. As with PSP emulation, we recommend using the unofficial desktop app, which enables the required browser features without compromising your security.
Minor changes
- Add custom session max age with
SESSION_MAX_AGE_SECONDS
by @zurdi15 in #1982 - Add stats summary back to the homepage as a display option by @zurdi15 in #1983
- Calculate hashes before fetching metadata by @gantoine in #1981
- Add TheGamesDB handler for platforms by @gantoine in #1994
- Use URL to store and load search params by @gantoine in #2045
- Add provider icons to scan page on match by @gantoine in #2084
- Random game button by @gantoine in #2091
- Add and update platform icons by @milktoastrat in #2000, #1980, #2007, #2021 and #2092
Fixes
- Added form rules that only allow ASCII chars on create user form by @zurdi15 in #1991
- Fix Retroachievements URL in README by @Azelphur in #1998
- Random fixes and improvements by @zurdi15 in #1999
- Use request body for user creation and update endpoints by @adamantike in #2012
- Specify English language for all Markdown blocks by @adamantike in #2029
- Add debounce to RomUser changes by @adamantike in #2028
- Set the correct forward proto when behind ssl proxy by @starkmapper in #2043
- Require threads for
dosbox_pure
core by @adamantike in #2054 - Only use first file in compressed game when calculating hashes by @gantoine in #2073
- Stop overwriting IDs on partial metadata scans by @gantoine in #2077
- Improve fuzzy matching in SGDBBaseHandler for game search by @zurdi15 in #2079
- Update roms_metadata virtual table by @gantoine in #2083
- SGDB cover fallback by @zurdi15 in #2087
- Load platform icon image source to prefer SVG over ICO format by @zurdi15 in #2089
Other changes
Warning
API endpoint changes
- Remove deprecated boolean parameters from
get_roms
endpoint by @adamantike in #2004 - Remove support for deprecated
GUNICORN_WORKERS
variable by @adamantike in #2003
- Provide Dockerfile for devs by @gantoine in #1960
- Remove
_request
method fromRAHandler
by @adamantike in #2005 - Update DEVELOPER_SETUP.md by @Konscription in #2016
- Remove unused methods from
roms_handler
by @adamantike in #2017 - Create ScreenScraper service adapter by @adamantike in #2002
- Create SteamGridDB service adapter by @adamantike in #2018
- Create MobyGames service adapter by @adamantike in #2023
- Improve API docs and annotations for rom endpoints by @adamantike in #2033
- Apply pyupgrade changes for Python 3.12 compatibility by @adamantike in #2034
- Improve API docs and annotations for platform endpoints by @adamantike in #2036
- Switch from poetry to uv by @gantoine in #2049
- Remove Python dependencies not being directly used by @adamantike in #2051
- Replace deprecated uvicorn.workers with uvicorn-worker by @adamantike in #2053
- Add code coverage for backend tests by @gantoine in #2056
- Correctly use Python 3.13 in Docker image by @adamantike in #2059
- Only subscribe to relevant filesystem events with watchdog by @adamantike in #2060
- Upgrade to Python 3.13 by @adamantike in #2048
- Upgrade nginx to v1.29.0 by @adamantike in #2035
- Upgrade py7zr to v1.0.0 by @adamantike in #2068
- Upgrade RALibretro to v1.8.1 by @adamantike in #2027
- Upgrade FastAPI to v0.116 by @adamantike in #2069
- Bump @intlify/core-base and vue-i18n in /frontend by @dependabot[bot] in #2088
New Contributors
- @milktoastrat made their first contribution in #1980
- @DevYukine made their first contribution in #1931
- @Azelphur made their first contribution in #1998
- @starkmapper made their first contribution in #2043
Full Changelog: 3.10.3...4.0.0