Files

207 lines
7.6 KiB
Markdown

# 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=<sessionid>
Headers: X-Requested-With: XMLHttpRequest, Referer: .../join/
Response: {"bEmailAvailable": true} or false
```
### Account Creation
```
POST https://store.steampowered.com/join/createaccount
Data:
accountname=<username>
password=<password>
email=<email>
email_confirm=<email>
captchagid=-1
captcha_text=
iAgree=1
ticket=
g-recaptcha-response=<2captcha_token>
count=7 # country code (7=US)
l=english
creation_sessionid=<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=<username>&donotcache=<timestamp_ms>
Response: {"success": true, "publickey_mod": "<hex>", "publickey_exp": "<hex>", "timestamp": "<ts>"}
# 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=<encrypted_b64>&rsatimestamp=<ts>&emailauth=<code>...
```
## 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:<uuid>&sms_phone_id=1&access_token=
[REDACTED] {"success": true, "shared_secret": "<base64>", "identity_secret": "<base64>", ...}
```
**Endpoint 2** (API — more reliable):
```
POST https://api.steampowered.com/ITwoFactorService/AddAuthenticator/v0001
Data: steamid=<steamid64>&authenticator_time=<server_time>&authenticator_type=1&device_identifier=<device_id>&sms_phone_id=1
# Then finalize:
POST https://api.steampowered.com/ITwoFactorService/FinalizeAddAuthenticator/v0001
Data: steamid=<steamid64>&authenticator_code=<generated_totp>&authenticator_time=<server_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=<custom>
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