Edit: Steam has updated the way IDs are calculated. I have updated this article to match.
const target = '"C:\\Program Files (x86)\\Origin\\Origin.exe"'; const label = 'Fubar Game'; const checksum = BigInt.asUintN(32, BigInt(require('crc').crc32(target + label))); const steamId = checksum | 0x80000000n; const top32 = steamId; const bottom32 = 0x02000000n; const legacySteamId = (top32 << 32n) | bottom32; console.log(steamId.toString(10)); console.log(legacySteamId.toString(10)); // 3934082902 // 16896757403876327424
Note: You can remove the Node.js dependency on the
crc package by replacing
require('crc').crc32(...) with any CRC32 implementation (example).
A Steam ID is a 32-bit unsigned integer. To derive it, first take the CRC32 checksum of the concatenated target and label UTF-8 encoded strings. Then set the top bit to 1. Meaning you concat the strings, calculate the checksum, and set the top bit.
A legacy Steam ID (still used in some places like Big Picture mode) is a 64-bit unsigned integer. The top 32 bits are the new Steam ID. The bottom 32 bits are the constant
0x02000000. Meaning you start with the new Steam ID, shift left 32 bits, and set the constant bits.
BigInt.asUintN(32, ...) to ensure the checksum is an unsigned 32-bit integer (some CRC32 implementations return negative numbers).
The values of the target and label strings should exactly match the values in the Steam UI (include double quotes if and only if they appear in Steam).