# Steam Account Registration — Platform-Specific Techniques Extends the `bulk-account-registration` pipeline with Steam-specific flows. Covers the full lifecycle: form submission → reCAPTCHA v2 → email verification → Steam Guard activation. ## Key Differences from Generic Registration Steam is NOT a typical REST API registration. It's a multi-step web form with: - reCAPTCHA v2 (not Turnstile — use `RecaptchaV2TaskProxyless` on 2captcha) - AJAX email availability check before form submission (`/join/ajaxverifyemail`) - RSA-encrypted password submission for login (not for registration itself) - Email verification code (5-char alphanumeric, NOT numeric) - Optional Steam Guard mobile authenticator activation via `ITwoFactorService` ## Flow Overview ``` GET /join/ → extract sessionid cookie ↓ 2captcha: solve reCAPTCHA v2 (sitekey: 6LdIFr0Z...) ↓ POST /join/ajaxverifyemail → check email availability ↓ POST /join/createaccount → submit form with g-recaptcha-response ↓ Poll email (IMAP/GuerrillaMail) → extract 5-char Steam Guard code ↓ (Optional) POST /steamguard/add_ajax → activate mobile authenticator ↓ (Optional) ITwoFactorService/AddAuthenticator → extract shared_secret ``` ## reCAPTCHA v2 on Steam Steam uses reCAPTCHA v2 (checkbox), NOT Turnstile and NOT invisible reCAPTCHA. **Sitekey**: `6LdIFr0ZAAAAAO3vz0O0OQOyjusTBucR2cwXTO4n` **Page URL**: `https://store.steampowered.com/join/` **2captcha solve** (via `createTask` API, not legacy `in.php`): ```python payload = { "clientKey": "YOUR_2CAPTCHA_KEY", "task": { "type": "RecaptchaV2TaskProxyless", "websiteURL": "https://store.steampowered.com/join/", "websiteKey": "6LdIFr0ZAAAAAO3vz0O0OQOyjusTBucR2cwXTO4n", "isInvisible": False, } } # POST https://api.2captcha.com/createTask → poll /getTaskResult # Solution field: solution.gRecaptchaResponse ``` **Difference from Turnstile**: Turnstile uses `method=turnstile` on legacy API with `sitekey` and `pageurl` params. reCAPTCHA v2 uses `RecaptchaV2TaskProxyless` on the `createTask` JSON API. Do NOT use Turnstile method for Steam — it's reCAPTCHA. ## Form Submission Details ### Email Availability Check ``` POST https://store.steampowered.com/join/ajaxverifyemail Data: email=user@domain.com&sessionid= Headers: X-Requested-With: XMLHttpRequest, Referer: .../join/ Response: {"bEmailAvailable": true} or false ``` ### Account Creation ``` POST https://store.steampowered.com/join/createaccount Data: accountname= password= email= email_confirm= captchagid=-1 captcha_text= iAgree=1 ticket= g-recaptcha-response=<2captcha_token> count=7 # country code (7=US) l=english creation_sessionid= ``` No RSA encryption needed for registration — that's only for login. ## RSA Password Encryption (Login Only) When logging into an existing account, Steam requires RSA-encrypted passwords: ```python # 1. Get RSA key POST https://store.steampowered.com/login/getrsakey/ Data: username=&donotcache= Response: {"success": true, "publickey_mod": "", "publickey_exp": "", "timestamp": ""} # 2. Encrypt password (PKCS1 v1.5) mod = int(publickey_mod, 16) exp = int(publickey_exp, 16) pw_int = int.from_bytes(password.encode("utf-8"), "big") encrypted_int = pow(pw_int, exp, mod) encrypted_b64 = base64.b64encode(encrypted_int.to_bytes(...)) # 3. Submit login POST https://store.steampowered.com/login/dologin/ Data: username=...&password=&rsatimestamp=&emailauth=... ``` ## Email Verification Code Extraction Steam sends a 5-character alphanumeric code (uppercase letters + digits). Pattern: ``` re.search(r'\b([A-Z0-9]{5})\b', email_body) ``` The email comes from `noreply@steampowered.com` with subject containing "Steam Guard". **IMAP search**: ```python client.search(["FROM", "noreply@steampowered.com"]) client.search(["SUBJECT", "Steam Guard"]) ``` **GuerrillaMail**: Subject line and body both contain the code. The `_extract_steam_code()` function handles HTML and plain text. ## Steam Guard Mobile Authenticator (TOTP) Steam uses a custom TOTP implementation: - **Algorithm**: HMAC-SHA1 - **Period**: 30 seconds - **Digits**: 5 - **Alphabet**: `23456789BCDFGHJKMNPQRTVWXY` (no 0, 1, A, E, I, O, L, S, U, Z — avoids ambiguous characters) ### TOTP Generation ```python import hmac, hashlib, base64, struct, time def generate_steam_totp(shared_secret_b64: str, timestamp: int = None) -> str: if timestamp is None: timestamp = int(time.time()) secret = [REDACTED]) time_bytes = struct.pack(">Q", timestamp // 30) hmac_result = hmac.new(secret, time_bytes, hashlib.sha1).digest() offset = hmac_result[-1] & 0x0F code_int = struct.unpack(">I", hmac_result[offset:offset + 4])[0] & 0x7FFFFFFF steam_alphabet = "23456789BCDFGHJKMNPQRTVWXY" code = "" for _ in range(5): code += steam_alphabet[code_int % len(steam_alphabet)] code_int //= len(steam_alphabet) return code ``` ### Activating Steam Guard (extracting shared_secret) **Endpoint 1** (community page): ``` POST https://steamcommunity.com/steamguard/add_ajax Data: sessionid=...&op=add_authenticator&device_identifier=android:&sms_phone_id=1&access_token= [REDACTED] {"success": true, "shared_secret": "", "identity_secret": "", ...} ``` **Endpoint 2** (API — more reliable): ``` POST https://api.steampowered.com/ITwoFactorService/AddAuthenticator/v0001 Data: steamid=&authenticator_time=&authenticator_type=1&device_identifier=&sms_phone_id=1 # Then finalize: POST https://api.steampowered.com/ITwoFactorService/FinalizeAddAuthenticator/v0001 Data: steamid=&authenticator_code=&authenticator_time=&activation_code= ``` **Device ID format**: `android:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (lowercase hex UUID). **Getting server time**: ``` POST https://api.steampowered.com/ITwoFactorService/QueryTime/v0001 Response: {"response": {"server_time": "1719600000"}} ``` ## SteamID64 Retrieval After login, SteamID64 appears in the URL: `https://steamcommunity.com/profiles/7656119XXXXXXXXXX/` Or resolve custom URL: ``` GET https://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key=&vanityurl= Response: {"response": {"steamid": "7656119XXXXXXXXXX", "success": 1}} ``` ## Pitfalls 1. **Don't use Turnstile method for Steam** — it's reCAPTCHA v2. Wrong method = wasted 2captcha balance. 2. **Steam Guard code is 5 chars, NOT 6** — unlike most OTP systems. Regex `\d{6}` will miss it. 3. **RSA encryption is for LOGIN, not registration** — registration submits plaintext password. 4. **`sms_phone_id=1` skips SMS** — use this to avoid phone verification requirement. 5. **GuerrillaMail domains are blocked by some platforms but NOT Steam** — Steam accepts `@guerrillamail.com` addresses. 6. **Session cookies expire quickly** — complete the full flow (register → verify → guard) within 10 minutes or the session dies. 7. **Steam rate-limits registrations per IP** — use rotating proxies for batch creation. Minimum 30-90s between accounts from same IP. 8. **Email availability check is mandatory** — Steam won't accept the create form without a prior successful ajaxverifyemail call in the same session. ## See Also - `bulk-account-registration` — general IMAP, proxy rotation, browser automation patterns - `references/multi-provider-imap-servers.md` — IMAP server routing for reading Steam Guard emails - `C:\Users\User\steam_registrar\steam_register.py` — complete working implementation