whalibmob 5.1.16 → 5.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example CHANGED
@@ -1,49 +1,44 @@
1
1
  # ─────────────────────────────────────────────────────────────────────────────
2
- # whalibmob — Device Emulation Configuration
2
+ # whalibmob — iPhone Device Emulation Configuration
3
3
  # Copy this file to .env in your project root and set the values you need.
4
- # All variables are optional; defaults emulate an iPhone 15 Pro running iOS 17.
4
+ # All variables are optional; the library picks a random iPhone by default.
5
5
  # ─────────────────────────────────────────────────────────────────────────────
6
6
 
7
- # Operating system to emulate. Accepted values: ios | android
8
- # Default: ios
9
- # WA_OS=android
10
-
11
- # Named device profile.
12
- #
13
- # iOS profiles (WA_OS=ios):
14
- # iphone_15_pro, iphone_15, iphone_14_pro, iphone_14, iphone_13_pro,
15
- # iphone_13, iphone_12_pro, iphone_12, iphone_11_pro, iphone_11,
16
- # iphone_se3, iphone_xs
7
+ # Named iPhone profile to emulate.
8
+ # If not set, the library picks a random iPhone from the list below.
17
9
  #
18
- # Android profiles (WA_OS=android):
19
- # pixel_8_pro, pixel_8, pixel_7, pixel_7a,
20
- # samsung_s24_ultra, samsung_s24, samsung_s23_ultra, samsung_s23, samsung_a55,
21
- # oneplus_12, oneplus_11, xiaomi_14, xiaomi_13, oppo_find_x7, realme_gt5
10
+ # Available profiles:
11
+ # iphone16promax, iphone16pro, iphone16plus, iphone16,
12
+ # iphone15promax, iphone15pro, iphone15plus, iphone15,
13
+ # iphone14promax, iphone14pro, iphone14plus, iphone14,
14
+ # iphone13pro, iphone13, iphone12pro, iphone12,
15
+ # iphone11pro, iphone11, iphonese3, iphonexs
22
16
  #
23
- # Default: iphone_15_pro (or pixel_8_pro when WA_OS=android)
24
- # WA_DEVICE=pixel_8_pro
17
+ # WA_DEVICE=iphone16pro
25
18
 
26
- # ── Custom device overrides (applied on top of the selected profile) ─────────
27
- # Use these to fine-tune any field without creating a new profile.
19
+ # ── Custom iPhone overrides ──────────────────────────────────────────────────
20
+ # Use these to emulate a specific iPhone model not in the list above.
21
+ # All values are sent as-is in the WhatsApp registration and connection.
28
22
 
29
- # WA_DEVICE_MODEL=SM-S928B
30
- # WA_DEVICE_MANUFACTURER=samsung
31
- # WA_DEVICE_OS_VERSION=14
32
- # WA_DEVICE_BUILD=UP1A.231005.007
33
- # WA_DEVICE_MODEL_ID=samsung-sm-s928b
23
+ # WA_DEVICE_MODEL=iPhone 16 Pro Max
24
+ # WA_DEVICE_OS_VERSION=18.3.2
25
+ # WA_DEVICE_BUILD=22D82
26
+ # WA_DEVICE_MODEL_ID=iPhone17,2
34
27
 
35
- # ── Version & token overrides ─────────────────────────────────────────────────
28
+ # ── Version & token overrides ────────────────────────────────────────────────
36
29
 
37
- # Pin the WhatsApp version string instead of fetching the latest from the store.
38
- # Format: 2.x.x.x (four-part)
39
- # WA_VERSION=2.24.13.80
30
+ # Pin the WhatsApp version string instead of fetching the latest from the
31
+ # App Store (iTunes lookup). Format: 2.x.x.x (four-part).
32
+ # WA_VERSION=2.26.10.74
40
33
 
41
- # Override the static token used in registration token computation.
42
- # Only needed if WhatsApp rotates the bundled token.
43
- # WA_STATIC_TOKEN=Y29Cs6AVNR2bj5PBeKSYFd1nAKuvNQ3h
34
+ # Override the built-in iOS static secret used in the token MD5 formula:
35
+ # token = MD5( WA_STATIC_TOKEN + MD5hex(version) + nationalNumber )
36
+ # Only needed if WhatsApp rotates the built-in secret.
37
+ # WA_STATIC_TOKEN=0a1mLfGUIBVrMKF1RdvLI5lkRBvof6vn0fD2QRSM
44
38
 
45
- # ── Proxy / Tor ───────────────────────────────────────────────────────────────
39
+ # ── Proxy / Tor ──────────────────────────────────────────────────────────────
46
40
 
47
41
  # Route registration HTTP traffic through a SOCKS5 proxy or Tor.
42
+ # Residential proxies recommended to avoid WhatsApp security blocks.
48
43
  # TOR_PROXY=socks5://127.0.0.1:9050
49
44
  # SOCKS_PROXY=socks5://user:pass@proxy.example.com:1080
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <div align='center'>whalibmob is a pure JavaScript Node.js library for interacting with the WhatsApp Mobile API.</div>
2
- <div align='center'>v5.1.14</div>
2
+ <div align='center'>v5.1.16</div>
3
3
 
4
4
  ##
5
5
 
@@ -10,7 +10,7 @@
10
10
  > This project is not affiliated, associated, authorized, endorsed by, or in any way officially connected with WhatsApp or any of its subsidiaries or affiliates. "WhatsApp" and related names are registered trademarks of their respective owners. Use at your own discretion.
11
11
 
12
12
  - whalibmob does not require a browser, Selenium, or any other external runtime — it communicates directly with WhatsApp using a **TCP socket** and the **Noise Protocol** handshake.
13
- - The library operates as a real **iOS mobile device**, not as WhatsApp Web. It uses the Mobile API endpoint, which behaves differently from the Web API.
13
+ - The library operates as a real **iOS mobile device** (iPhone), not as WhatsApp Web. It uses the Mobile API endpoint, which behaves differently from the Web API.
14
14
  - Signal Protocol encryption is **fully inlined** in pure JavaScript — no native binaries, no node-gyp, runs anywhere Node.js runs.
15
15
 
16
16
  ## Install
@@ -184,9 +184,8 @@ npm install -g whalibmob
184
184
  - [Media Encryption](#media-encryption)
185
185
  - [Device Emulation](#device-emulation)
186
186
  - [Quick Start](#device-quick-start)
187
- - [iOS Profiles](#ios-profiles)
188
- - [Android Profiles](#android-profiles)
189
- - [Custom Device Fields](#custom-device-fields)
187
+ - [iPhone Profiles](#iphone-profiles)
188
+ - [Custom iPhone Fields](#custom-iphone-fields)
190
189
  - [Version & Token Overrides](#version--token-overrides)
191
190
 
192
191
  ---
@@ -2186,18 +2185,20 @@ See the [Receiving Media](#receiving-media) section for a complete working code
2186
2185
 
2187
2186
  ## Device Emulation
2188
2187
 
2189
- whalibmob can emulate any iOS or Android device when communicating with WhatsApp servers.
2190
- The device profile controls the User-Agent header, the Noise Protocol `platform` field, and the static token used in registration token computation.
2188
+ whalibmob emulates an iPhone when communicating with WhatsApp servers.
2189
+ The device profile controls the User-Agent header, the Noise Protocol `platform` field, and the token computation.
2190
+
2191
+ When no `WA_DEVICE` is set, the library **picks a random iPhone model** from the built-in profile list for each new session. This provides natural device diversity.
2191
2192
 
2192
2193
  Configuration is done entirely through environment variables — no code changes required.
2193
2194
  Copy `.env.example` to `.env` in your project root and set the variables you need.
2194
2195
 
2195
2196
  ### Device Quick Start
2196
2197
 
2197
- Emulate an Android Pixel 8 Pro:
2198
+ Emulate an iPhone 16 Pro:
2198
2199
 
2199
2200
  ```sh
2200
- WA_OS=android WA_DEVICE=pixel_8_pro node your-app.js
2201
+ WA_DEVICE=iphone16pro node your-app.js
2201
2202
  ```
2202
2203
 
2203
2204
  Or put the variables in a `.env` file. When using the **CLI** (`wa` command) the file is loaded automatically. When using the **library directly**, load it before `require('whalibmob')`:
@@ -2208,86 +2209,86 @@ const { WhalibmobClient } = require('whalibmob')
2208
2209
  ```
2209
2210
 
2210
2211
  ```dotenv
2211
- WA_OS=android
2212
- WA_DEVICE=pixel_8_pro
2213
- ```
2214
-
2215
- Emulate a custom Samsung device:
2216
-
2217
- ```dotenv
2218
- WA_OS=android
2219
- WA_DEVICE_MODEL=SM-S928B
2220
- WA_DEVICE_MANUFACTURER=samsung
2221
- WA_DEVICE_OS_VERSION=14
2222
- WA_DEVICE_BUILD=UP1A.231005.007
2223
- WA_DEVICE_MODEL_ID=samsung-sm-s928b
2212
+ WA_DEVICE=iphone16pro
2224
2213
  ```
2225
2214
 
2226
- ### iOS Profiles
2215
+ ### iPhone Profiles
2227
2216
 
2228
- Available values for `WA_DEVICE` when `WA_OS=ios` (default):
2217
+ Available values for `WA_DEVICE`:
2229
2218
 
2230
2219
  | Profile key | Device | iOS version |
2231
2220
  |---|---|---|
2232
- | `iphone_15_pro` | iPhone 15 Pro | 17.4.1 |
2233
- | `iphone_15` | iPhone 15 | 17.4.1 |
2234
- | `iphone_14_pro` | iPhone 14 Pro | 16.7.5 |
2235
- | `iphone_14` | iPhone 14 | 16.7.5 |
2236
- | `iphone_13_pro` | iPhone 13 Pro | 16.7.5 |
2237
- | `iphone_13` | iPhone 13 | 16.7.5 |
2238
- | `iphone_12_pro` | iPhone 12 Pro | 15.8.2 |
2239
- | `iphone_12` | iPhone 12 | 15.8.2 |
2240
- | `iphone_11_pro` | iPhone 11 Pro | 15.8.2 |
2241
- | `iphone_11` | iPhone 11 | 15.8.2 |
2242
- | `iphone_se3` | iPhone SE (3rd gen) | 16.7.5 |
2243
- | `iphone_xs` | iPhone Xs | 15.8.2 |
2244
-
2245
- iOS User-Agent format: `WhatsApp/<version> iOS/<osVersion> Device/<model>`
2246
-
2247
- ### Android Profiles
2248
-
2249
- Available values for `WA_DEVICE` when `WA_OS=android`:
2250
-
2251
- | Profile key | Device | Android version |
2221
+ | `iphone16promax` | iPhone 16 Pro Max | 18.3.2 |
2222
+ | `iphone16pro` | iPhone 16 Pro | 18.3.2 |
2223
+ | `iphone16plus` | iPhone 16 Plus | 18.3.2 |
2224
+ | `iphone16` | iPhone 16 | 18.3.2 |
2225
+ | `iphone15promax` | iPhone 15 Pro Max | 18.3.2 |
2226
+ | `iphone15pro` | iPhone 15 Pro | 18.3.2 |
2227
+ | `iphone15plus` | iPhone 15 Plus | 18.3.2 |
2228
+ | `iphone15` | iPhone 15 | 18.3.2 |
2229
+ | `iphone14promax` | iPhone 14 Pro Max | 18.3.2 |
2230
+ | `iphone14pro` | iPhone 14 Pro | 18.3.2 |
2231
+ | `iphone14plus` | iPhone 14 Plus | 17.7.5 |
2232
+ | `iphone14` | iPhone 14 | 17.7.5 |
2233
+ | `iphone13pro` | iPhone 13 Pro | 17.7.5 |
2234
+ | `iphone13` | iPhone 13 | 17.7.5 |
2235
+ | `iphone12pro` | iPhone 12 Pro | 17.7.5 |
2236
+ | `iphone12` | iPhone 12 | 17.7.5 |
2237
+ | `iphonese3` | iPhone SE (3rd gen) | 17.7.5 |
2238
+ | `iphone11pro` | iPhone 11 Pro | 17.7.5 |
2239
+ | `iphone11` | iPhone 11 | 17.7.5 |
2240
+ | `iphonexs` | iPhone Xs | 16.7.11 |
2241
+
2242
+ User-Agent format: `WhatsApp/<version> iOS/<osVersion> Device/<model>`
2243
+
2244
+ The WhatsApp version is fetched automatically from the Apple App Store (iTunes API) every time you register, always using the latest published version. The result is cached for **6 hours** so repeated calls within a session are fast. If all App Store sources fail (no internet, rate limit, etc.), the built-in `IOS_VERSION_FALLBACK` constant is used as a last resort. Three iTunes API endpoints are tried in sequence for maximum reliability.
2245
+
2246
+ ### Custom iPhone Fields
2247
+
2248
+ These variables override individual fields to emulate a specific iPhone not in the list above.
2249
+
2250
+ | Variable | Sent to WhatsApp as | Notes |
2252
2251
  |---|---|---|
2253
- | `pixel_8_pro` | Pixel 8 Pro | 14 |
2254
- | `pixel_8` | Pixel 8 | 14 |
2255
- | `pixel_7` | Pixel 7 | 14 |
2256
- | `pixel_7a` | Pixel 7a | 14 |
2257
- | `samsung_s24_ultra` | Samsung Galaxy S24 Ultra | 14 |
2258
- | `samsung_s24` | Samsung Galaxy S24 | 14 |
2259
- | `samsung_s23_ultra` | Samsung Galaxy S23 Ultra | 14 |
2260
- | `samsung_s23` | Samsung Galaxy S23 | 14 |
2261
- | `samsung_a55` | Samsung Galaxy A55 | 14 |
2262
- | `oneplus_12` | OnePlus 12 | 14 |
2263
- | `oneplus_11` | OnePlus 11 | 13 |
2264
- | `xiaomi_14` | Xiaomi 14 | 14 |
2265
- | `xiaomi_13` | Xiaomi 13 | 13 |
2266
- | `oppo_find_x7` | OPPO Find X7 | 14 |
2267
- | `realme_gt5` | realme GT 5 Pro | 14 |
2268
-
2269
- Android User-Agent format: `WhatsApp/<version> A`
2270
-
2271
- The Android version is fetched automatically from the Google Play Store on first use and cached in memory. If the fetch fails, `ANDROID_VERSION_FALLBACK` is used.
2272
-
2273
- ### Custom Device Fields
2274
-
2275
- These variables override individual fields on top of the selected profile:
2252
+ | `WA_DEVICE_MODEL` | proto field 7 | e.g. `iPhone 16 Pro Max` |
2253
+ | `WA_DEVICE_OS_VERSION` | proto field 5 | e.g. `18.3.2` or `17.4.1` |
2254
+ | `WA_DEVICE_BUILD` | proto field 8 | iOS build number, e.g. `22D82` |
2255
+ | `WA_DEVICE_MODEL_ID` | proto field 16 | Apple model number, e.g. `iPhone17,2` |
2276
2256
 
2277
- | Variable | Description |
2278
- |---|---|
2279
- | `WA_DEVICE_MODEL` | Device model string (e.g. `SM-S928B`) |
2280
- | `WA_DEVICE_MANUFACTURER` | Manufacturer name (e.g. `samsung`) |
2281
- | `WA_DEVICE_OS_VERSION` | OS version string (e.g. `14`) |
2282
- | `WA_DEVICE_BUILD` | Build fingerprint (e.g. `UP1A.231005.007`) |
2283
- | `WA_DEVICE_MODEL_ID` | Model ID slug (e.g. `samsung-sm-s928b`) |
2257
+ > [!NOTE]
2258
+ > These fields are sent in the **Noise Protocol handshake** (TCP connection to WhatsApp), not in the HTTP registration body. The HTTP registration body sends identity keys, token, `mcc`/`mnc`/`sim_mcc`/`sim_mnc` (derived from the country code), and locale (`lg`/`lc`) — it does **not** send the human-readable device strings.
2259
+
2260
+ **Example custom iPhone via Node.js API:**
2261
+
2262
+ ```js
2263
+ process.env.WA_DEVICE_MODEL = 'iPhone 16 Pro Max'
2264
+ process.env.WA_DEVICE_OS_VERSION = '18.3.2'
2265
+ process.env.WA_DEVICE_BUILD = '22D82'
2266
+ process.env.WA_DEVICE_MODEL_ID = 'iPhone17,2'
2267
+
2268
+ const { createNewStore, requestSmsCode, verifyCode } = require('whalibmob')
2269
+
2270
+ const store = createNewStore('919634847671')
2271
+ await requestSmsCode(store, 'sms')
2272
+ ```
2273
+
2274
+ **Example — custom iPhone via `.env` file:**
2275
+
2276
+ ```dotenv
2277
+ WA_DEVICE_MODEL=iPhone 16 Pro Max
2278
+ WA_DEVICE_OS_VERSION=18.3.2
2279
+ WA_DEVICE_BUILD=22D82
2280
+ WA_DEVICE_MODEL_ID=iPhone17,2
2281
+ ```
2284
2282
 
2285
2283
  ### Version & Token Overrides
2286
2284
 
2287
2285
  | Variable | Description |
2288
2286
  |---|---|
2289
- | `WA_VERSION` | Pin the WhatsApp version (e.g. `2.24.13.80`). Skips the live store fetch. |
2290
- | `WA_STATIC_TOKEN` | Override the static token used in registration token computation. |
2287
+ | `WA_VERSION` | Pin a specific WhatsApp version (e.g. `2.26.10.74`). Skips the live App Store fetch entirely. |
2288
+ | `WA_STATIC_TOKEN` | Replaces the built-in iOS static secret in the MD5 formula (`token = MD5(secret + MD5hex(version) + national)`). Only needed if WhatsApp rotates the built-in secret. |
2289
+
2290
+ > [!NOTE]
2291
+ > **No token configuration is needed.** The built-in iOS static secret (`IOS_STATIC_TOKEN`) is valid for current WhatsApp servers. `WA_STATIC_TOKEN` is only needed if that secret is rotated in a future WhatsApp update.
2291
2292
 
2292
2293
  ## License
2293
2294
 
package/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  // Load .env from the current working directory (silently — no error if missing).
5
- // This lets users configure WA_OS, WA_DEVICE, WA_VERSION etc. without touching
5
+ // This lets users configure WA_DEVICE, WA_VERSION etc. without touching
6
6
  // their shell environment. Must happen before any other require() so that
7
7
  // process.env is fully populated when modules read it at load time.
8
8
  try { require('dotenv').config(); } catch (_) {}
@@ -35,7 +35,7 @@ const {
35
35
  loadStore
36
36
  } = require('./lib/Client');
37
37
 
38
- const VERSION = '5.1.15';
38
+ const VERSION = '5.1.16';
39
39
 
40
40
  // ─── output helpers ───────────────────────────────────────────────────────────
41
41
 
package/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  const { WhalibmobClient, checkNumberStatus, fetchIosVersion, fetchWaVersion, assertRegistrationKeys } = require('./lib/Client');
4
4
  const { getDeviceConfig } = require('./lib/DeviceConfig');
5
- const { fetchAndroidVersion } = require('./lib/Registration');
6
5
  const { createNewStore, saveStore, loadStore, toSixParts, fromSixParts, storeToJson, storeFromJson } = require('./lib/Store');
7
6
  const { checkIfRegistered, requestSmsCode, verifyCode } = require('./lib/Registration');
8
7
  const { SignalProtocol } = require('./lib/signal/SignalProtocol');
@@ -19,12 +18,11 @@ module.exports = {
19
18
  requestSmsCode,
20
19
  verifyCode,
21
20
  assertRegistrationKeys,
22
- // Version fetch — use fetchWaVersion for device-aware (iOS or Android) fetching.
21
+ // Version fetch — fetchWaVersion fetches from the Apple App Store.
23
22
  // fetchIosVersion is kept for backward compatibility.
24
23
  fetchWaVersion,
25
24
  fetchIosVersion,
26
- fetchAndroidVersion,
27
- // Device config — reads WA_OS / WA_DEVICE / WA_DEVICE_* from process.env
25
+ // Device config — reads WA_DEVICE / WA_DEVICE_* from process.env
28
26
  getDeviceConfig,
29
27
  // Store helpers
30
28
  createNewStore,
@@ -2,80 +2,65 @@
2
2
 
3
3
  const {
4
4
  IOS_DEVICE,
5
- IOS_DEVICE_PROFILES,
6
- ANDROID_DEVICE_PROFILES
5
+ IOS_DEVICE_PROFILES
7
6
  } = require('./constants');
8
7
 
9
- // Pre-build normalised lookup tables so that user-supplied profile keys in any
8
+ // Pre-build normalised lookup table so that user-supplied profile keys in any
10
9
  // separator style (underscores, dashes, spaces, or none) always resolve.
11
10
  // Normalisation: lowercase, strip underscores / dashes / spaces.
12
11
  function _normalise(s) { return String(s).toLowerCase().replace(/[\s_-]/g, ''); }
13
12
 
14
- const _IOS_MAP = {};
15
- const _ANDROID_MAP = {};
16
- for (const k of Object.keys(IOS_DEVICE_PROFILES)) _IOS_MAP[_normalise(k)] = IOS_DEVICE_PROFILES[k];
17
- for (const k of Object.keys(ANDROID_DEVICE_PROFILES)) _ANDROID_MAP[_normalise(k)] = ANDROID_DEVICE_PROFILES[k];
13
+ const _IOS_MAP = {};
14
+ const _IOS_KEYS = [];
15
+ for (const k of Object.keys(IOS_DEVICE_PROFILES)) {
16
+ _IOS_MAP[_normalise(k)] = IOS_DEVICE_PROFILES[k];
17
+ _IOS_KEYS.push(k);
18
+ }
18
19
 
19
20
  // ─────────────────────────────────────────────────────────────────────────────
20
- // DeviceConfig — reads environment variables and returns the active device
21
+ // DeviceConfig — reads environment variables and returns the active iOS device
21
22
  // profile to be used during registration and connection.
22
23
  //
23
24
  // Priority order:
24
- // 1. WA_OS + WA_DEVICE → pick a named predefined profile
25
- // 2. WA_OS + individual WA_DEVICE_* vars → build a custom profile
26
- // 3. No env vars default iOS (iPhone 15 Pro)
25
+ // 1. WA_DEVICE → pick a named predefined iPhone profile
26
+ // 2. WA_DEVICE_* variables → build a custom iOS profile
27
+ // 3. No env vars random iPhone from the profile list
27
28
  //
28
29
  // Env variables:
29
- // WA_OS ios | android (default: ios)
30
- // WA_DEVICE profile key (e.g. samsung-s24-ultra, pixel8, iphone14)
31
- // WA_DEVICE_MODEL device display name
32
- // WA_DEVICE_MANUFACTURER Apple | Samsung | Google …
33
- // WA_DEVICE_OS_VERSION OS version string (e.g. 17.4.1 or 14)
34
- // WA_DEVICE_BUILD OS build number
35
- // WA_DEVICE_MODEL_ID internal model identifier (e.g. SM-S928B, iPhone16,1)
30
+ // WA_DEVICE profile key (e.g. iphone16pro, iphone15, iphonese3)
31
+ // WA_DEVICE_MODEL device display name (e.g. "iPhone 16 Pro Max")
32
+ // WA_DEVICE_OS_VERSION iOS version string (e.g. "18.3.2")
33
+ // WA_DEVICE_BUILD iOS build number (e.g. "22D82")
34
+ // WA_DEVICE_MODEL_ID internal model id (e.g. "iPhone17,2")
36
35
  // WA_VERSION override WhatsApp version (skips live fetch if set)
37
- // WA_STATIC_TOKEN override static registration token
36
+ // WA_STATIC_TOKEN override static registration token secret
38
37
  // ─────────────────────────────────────────────────────────────────────────────
39
38
 
40
39
  function getDeviceConfig() {
41
- const osType = (process.env.WA_OS || 'ios').toLowerCase().trim();
42
-
43
- if (osType === 'android') {
44
- const profileKey = _normalise(process.env.WA_DEVICE || 'samsungs24ultra');
45
- const found = _ANDROID_MAP[profileKey] || null;
46
- if (found) {
47
- return Object.assign({}, found);
48
- }
40
+ // 1. Named profile via WA_DEVICE
41
+ if (process.env.WA_DEVICE) {
42
+ const profileKey = _normalise(process.env.WA_DEVICE);
43
+ const found = _IOS_MAP[profileKey] || null;
44
+ if (found) return Object.assign({}, found);
45
+ }
49
46
 
47
+ // 2. Custom profile via individual WA_DEVICE_* vars
48
+ if (process.env.WA_DEVICE_MODEL || process.env.WA_DEVICE_MODEL_ID) {
50
49
  return {
51
- os: 'android',
52
- platform: 3,
53
- model: process.env.WA_DEVICE_MODEL || 'Samsung Galaxy S24 Ultra',
54
- manufacturer: process.env.WA_DEVICE_MANUFACTURER || 'Samsung',
55
- osVersion: process.env.WA_DEVICE_OS_VERSION || '14',
56
- osBuildNumber: process.env.WA_DEVICE_BUILD || 'UP1A.231005.007',
57
- modelId: process.env.WA_DEVICE_MODEL_ID || 'SM-S928B',
50
+ os: 'ios',
51
+ platform: 1,
52
+ model: process.env.WA_DEVICE_MODEL || IOS_DEVICE.model,
53
+ manufacturer: 'Apple',
54
+ osVersion: process.env.WA_DEVICE_OS_VERSION || IOS_DEVICE.osVersion,
55
+ osBuildNumber: process.env.WA_DEVICE_BUILD || IOS_DEVICE.osBuildNumber,
56
+ modelId: process.env.WA_DEVICE_MODEL_ID || IOS_DEVICE.modelId,
58
57
  deviceModelType: 2
59
58
  };
60
59
  }
61
60
 
62
- // iOS (default)
63
- const profileKey = _normalise(process.env.WA_DEVICE || 'iphone15pro');
64
- const found = _IOS_MAP[profileKey] || null;
65
- if (found) {
66
- return Object.assign({}, found);
67
- }
68
-
69
- return {
70
- os: 'ios',
71
- platform: 1,
72
- model: process.env.WA_DEVICE_MODEL || IOS_DEVICE.model,
73
- manufacturer: process.env.WA_DEVICE_MANUFACTURER || IOS_DEVICE.manufacturer,
74
- osVersion: process.env.WA_DEVICE_OS_VERSION || IOS_DEVICE.osVersion,
75
- osBuildNumber: process.env.WA_DEVICE_BUILD || IOS_DEVICE.osBuildNumber,
76
- modelId: process.env.WA_DEVICE_MODEL_ID || IOS_DEVICE.modelId,
77
- deviceModelType: 2
78
- };
61
+ // 3. No env vars → pick a random iPhone profile for device diversity
62
+ const idx = Math.floor(Math.random() * _IOS_KEYS.length);
63
+ return Object.assign({}, IOS_DEVICE_PROFILES[_IOS_KEYS[idx]]);
79
64
  }
80
65
 
81
66
  module.exports = { getDeviceConfig };
@@ -120,7 +120,7 @@ function _tryUpload(host, mediaPath, token, auth, encrypted, encSha256, sha256)
120
120
  'Content-Type': 'application/octet-stream',
121
121
  'Content-Length': encrypted.length,
122
122
  'Accept': 'application/json',
123
- 'User-Agent': (() => { const d = getDeviceConfig(); return d.os === 'android' ? `WhatsApp/${d.version || '2.26.7.75'} A` : `WhatsApp/${d.version || '2.26.7.75'} iOS/${d.osVersion} Device/${d.model}`; })()
123
+ 'User-Agent': (() => { const d = getDeviceConfig(); return `WhatsApp/${d.version || '2.26.10.74'} iOS/${d.osVersion} Device/${d.model}`; })()
124
124
  }
125
125
  };
126
126
 
@@ -38,9 +38,7 @@ async function httpPostViaSocks(path, body, waVersion, proxyUrl) {
38
38
  });
39
39
 
40
40
  const _dev = getDeviceConfig();
41
- const userAgent = _dev.os === 'android'
42
- ? `WhatsApp/${waVersion} A`
43
- : `WhatsApp/${waVersion} iOS/${_dev.osVersion} Device/${_dev.model}`;
41
+ const userAgent = `WhatsApp/${waVersion} iOS/${_dev.osVersion} Device/${_dev.model}`;
44
42
  const req = [
45
43
  `POST /v2${path} HTTP/1.1`,
46
44
  `Host: ${dHost}`,
@@ -90,9 +88,7 @@ const {
90
88
  REGISTRATION_ENDPOINT,
91
89
  REGISTRATION_PUBLIC_KEY,
92
90
  IOS_STATIC_TOKEN,
93
- ANDROID_STATIC_TOKEN,
94
91
  IOS_VERSION_FALLBACK,
95
- ANDROID_VERSION_FALLBACK,
96
92
  IOS_USER_AGENT,
97
93
  IOS_DEVICE,
98
94
  SIGNAL_KEY_TYPE,
@@ -231,93 +227,93 @@ function parsePhone(phoneNumber) {
231
227
  return { cc: cc1, national: String(BigInt(str.slice(1))) };
232
228
  }
233
229
 
234
- // ---------- WhatsApp version fetch (iOS from iTunes, Android from Play Store) ----------
230
+ // ---------- WhatsApp version fetch (from Apple App Store / iTunes) ----------
235
231
 
236
- let _cachedIosVersion = null;
237
- let _cachedAndroidVersion = null;
232
+ // Version cache with TTL — re-fetches every 6 hours so long-running processes
233
+ // always use the current App Store version, not a stale one from startup.
234
+ const VERSION_CACHE_TTL_MS = 6 * 60 * 60 * 1000; // 6 hours
235
+ let _versionCache = { version: null, fetchedAt: 0 };
238
236
 
239
- async function fetchIosVersion() {
240
- if (_cachedIosVersion) return _cachedIosVersion;
237
+ // Fetch JSON from a single iTunes API URL. Resolves to a version string or null.
238
+ function _fetchFromUrl(url) {
241
239
  return new Promise((resolve) => {
242
- const req = https.get(
243
- 'https://itunes.apple.com/lookup?bundleId=net.whatsapp.WhatsApp',
244
- { headers: { 'User-Agent': IOS_USER_AGENT } },
245
- (res) => {
246
- const chunks = [];
247
- res.on('data', d => chunks.push(d));
248
- res.on('end', () => {
249
- try {
250
- const json = JSON.parse(Buffer.concat(chunks).toString('utf8'));
251
- let ver = (json.results && json.results[0] && json.results[0].version) || IOS_VERSION_FALLBACK;
252
- if (!ver.startsWith('2.')) ver = '2.' + ver;
253
- _cachedIosVersion = ver;
254
- resolve(ver);
255
- } catch (_) {
256
- resolve(IOS_VERSION_FALLBACK);
257
- }
258
- });
240
+ const req = https.get(url, { headers: { 'User-Agent': IOS_USER_AGENT } }, (res) => {
241
+ // Follow one redirect (iTunes sometimes 301 → 200)
242
+ if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location) {
243
+ resolve(_fetchFromUrl(res.headers.location));
244
+ return;
259
245
  }
260
- );
261
- req.on('error', () => resolve(IOS_VERSION_FALLBACK));
262
- req.setTimeout(8000, () => { req.destroy(); resolve(IOS_VERSION_FALLBACK); });
246
+ const chunks = [];
247
+ res.on('data', d => chunks.push(d));
248
+ res.on('end', () => {
249
+ try {
250
+ const json = JSON.parse(Buffer.concat(chunks).toString('utf8'));
251
+ const raw = json.results && json.results[0] && json.results[0].version;
252
+ if (!raw) return resolve(null);
253
+ let ver = String(raw).trim();
254
+ if (!ver.startsWith('2.')) ver = '2.' + ver;
255
+ resolve(ver);
256
+ } catch (_) {
257
+ resolve(null);
258
+ }
259
+ });
260
+ });
261
+ req.on('error', () => resolve(null));
262
+ req.setTimeout(8000, () => { req.destroy(); resolve(null); });
263
263
  });
264
264
  }
265
265
 
266
- // Fetch latest WhatsApp Android version from Google Play Store.
267
- // Parses the 4-part "2.x.x.x" version string embedded in the page JSON data.
268
- // Falls back to ANDROID_VERSION_FALLBACK on any error.
269
- async function fetchAndroidVersion() {
270
- if (_cachedAndroidVersion) return _cachedAndroidVersion;
271
- try {
272
- const axios = require('axios');
273
- const resp = await axios.get(
274
- 'https://play.google.com/store/apps/details?id=com.whatsapp&hl=en&gl=us',
275
- {
276
- headers: {
277
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
278
- 'Accept-Language': 'en-US,en;q=0.9'
279
- },
280
- timeout: 12000
281
- }
282
- );
283
- const html = String(resp.data);
284
-
285
- // Primary: first quoted 4-part version string matching WhatsApp's "2.x.x.x" scheme.
286
- // In Play Store JSON the current stable version appears first, before beta/history entries.
287
- const primary = html.match(/"(2\.\d+\.\d+\.\d+)"/);
288
- if (primary) {
289
- _cachedAndroidVersion = primary[1];
290
- return primary[1];
291
- }
266
+ // Live App Store sources, tried in order until one succeeds.
267
+ // Multiple endpoints provide resilience against CDN hiccups and region blocks.
268
+ const IOS_VERSION_SOURCES = [
269
+ 'https://itunes.apple.com/lookup?bundleId=net.whatsapp.WhatsApp&country=us',
270
+ 'https://itunes.apple.com/lookup?bundleId=net.whatsapp.WhatsApp',
271
+ 'https://itunes.apple.com/lookup?bundleId=net.whatsapp.WhatsApp&country=gb',
272
+ ];
273
+
274
+ // Fetch and return the latest WhatsApp iOS version from the Apple App Store.
275
+ // Results are cached for VERSION_CACHE_TTL_MS (6 hours) so long-running
276
+ // servers automatically pick up new releases without a restart.
277
+ // Set WA_VERSION env var to pin a specific version and skip the live fetch.
278
+ async function fetchIosVersion() {
279
+ const now = Date.now();
280
+ if (_versionCache.version && (now - _versionCache.fetchedAt) < VERSION_CACHE_TTL_MS) {
281
+ return _versionCache.version;
282
+ }
292
283
 
293
- // Secondary: unquoted version adjacent to "WhatsApp" text (catches alternate HTML structures).
294
- const secondary = html.match(/WhatsApp[^<"]{0,200}?(2\.\d+\.\d+\.\d+)/);
295
- if (secondary) {
296
- _cachedAndroidVersion = secondary[1];
297
- return secondary[1];
284
+ // Try each source in order return the first successful result
285
+ for (const url of IOS_VERSION_SOURCES) {
286
+ const ver = await _fetchFromUrl(url);
287
+ if (ver) {
288
+ _versionCache = { version: ver, fetchedAt: now };
289
+ console.error(`[DBG] fetchIosVersion: ${ver} (source: ${url})`);
290
+ return ver;
298
291
  }
299
- } catch (_) {}
300
- return ANDROID_VERSION_FALLBACK;
292
+ }
293
+
294
+ // All sources failed — use fallback constant (and don't cache it so next call retries)
295
+ console.error(`[DBG] fetchIosVersion: all sources failed, using fallback ${IOS_VERSION_FALLBACK}`);
296
+ return IOS_VERSION_FALLBACK;
301
297
  }
302
298
 
303
- // Return the appropriate WhatsApp version for the active device.
304
- // If WA_VERSION is set in the environment, that value is always used.
305
- async function fetchWaVersion(device) {
299
+ // Return the latest WhatsApp iOS version.
300
+ // If WA_VERSION is set in the environment, that value is always used (no fetch).
301
+ async function fetchWaVersion() {
306
302
  if (process.env.WA_VERSION) return process.env.WA_VERSION;
307
- return (device && device.os === 'android') ? fetchAndroidVersion() : fetchIosVersion();
303
+ return fetchIosVersion();
308
304
  }
309
305
 
310
306
  // ---------- Token computation ----------
311
- // token = MD5( staticToken + MD5hex(waVersion) + nationalNumber )
312
- // The static token depends on the platform (iOS vs Android).
313
- // Override with WA_STATIC_TOKEN in .env if the bundled token becomes stale.
307
+ //
308
+ // iOS token formula:
309
+ // token = MD5( staticSecret + MD5hex(waVersion) + nationalNumber )
310
+ // The staticSecret is IOS_STATIC_TOKEN unless WA_STATIC_TOKEN is set.
311
+ // This algorithm is accepted by WhatsApp servers as of 2.26.x.
314
312
 
315
313
  function computeToken(waVersion, national) {
316
- const device = getDeviceConfig();
317
- const staticToken = process.env.WA_STATIC_TOKEN
318
- || (device.os === 'android' ? ANDROID_STATIC_TOKEN : IOS_STATIC_TOKEN);
314
+ const secret = process.env.WA_STATIC_TOKEN || IOS_STATIC_TOKEN;
319
315
  const versionHashHex = md5Bytes(waVersion).toString('hex');
320
- return md5Hex(staticToken + versionHashHex + national);
316
+ return md5Hex(secret + versionHashHex + national);
321
317
  }
322
318
 
323
319
  // ---------- Byte helpers ----------
@@ -372,26 +368,31 @@ function buildPayload(store, waVersion, useToken, extraPairs) {
372
368
  const { cc, national } = parsePhone(store.phoneNumber);
373
369
  const token = useToken ? computeToken(waVersion, national) : null;
374
370
  const fdid = store.fdid.toUpperCase();
375
- const device = (store.device && store.device.platform != null) ? store.device : getDeviceConfig();
371
+ const meta = getCountryMeta(cc);
376
372
 
377
373
  return buildForm([
378
- 'cc', cc,
379
- 'in', national,
380
- 'rc', String(RELEASE_CHANNEL),
381
- 'lg', 'en',
382
- 'lc', 'US',
383
- 'platform', String(device.platform),
384
- 'authkey', toBase64Url(stripKeyPrefix(store.noiseKeyPair.public)),
385
- 'e_regid', toBase64Url(intToBytes(store.registrationId, 4)),
386
- 'e_keytype', toBase64Url(Buffer.from([SIGNAL_KEY_TYPE])),
387
- 'e_ident', toBase64Url(stripKeyPrefix(store.identityKeyPair.public)),
388
- 'e_skey_id', toBase64Url(intToBytes(store.signedPreKey.id, 3)),
374
+ 'cc', cc,
375
+ 'in', national,
376
+ 'rc', String(RELEASE_CHANNEL),
377
+ 'lg', meta.lg || 'en',
378
+ 'lc', meta.lc || 'US',
379
+ 'mcc', meta.mcc,
380
+ 'mnc', meta.mnc,
381
+ 'sim_mcc', meta.mcc,
382
+ 'sim_mnc', meta.mnc,
383
+ 'platform', '1',
384
+ 'hasinrc', '0',
385
+ 'authkey', toBase64Url(stripKeyPrefix(store.noiseKeyPair.public)),
386
+ 'e_regid', toBase64Url(intToBytes(store.registrationId, 4)),
387
+ 'e_keytype', toBase64Url(Buffer.from([SIGNAL_KEY_TYPE])),
388
+ 'e_ident', toBase64Url(stripKeyPrefix(store.identityKeyPair.public)),
389
+ 'e_skey_id', toBase64Url(intToBytes(store.signedPreKey.id, 3)),
389
390
  'e_skey_val', toBase64Url(stripKeyPrefix(store.signedPreKey.public)),
390
391
  'e_skey_sig', toBase64Url(store.signedPreKey.signature),
391
- 'fdid', fdid,
392
- 'expid', toBase64Url(store.deviceId),
393
- 'id', toUrlHex(store.identityId),
394
- 'token', token
392
+ 'fdid', fdid,
393
+ 'expid', toBase64Url(store.deviceId),
394
+ 'id', toUrlHex(store.identityId),
395
+ 'token', token
395
396
  ], extraPairs);
396
397
  }
397
398
 
@@ -418,9 +419,7 @@ function httpPost(path, body, waVersion) {
418
419
 
419
420
  return new Promise((resolve, reject) => {
420
421
  const _httpDev = getDeviceConfig();
421
- const userAgent = _httpDev.os === 'android'
422
- ? `WhatsApp/${waVersion} A`
423
- : `WhatsApp/${waVersion} iOS/${_httpDev.osVersion} Device/${_httpDev.model}`;
422
+ const userAgent = `WhatsApp/${waVersion} iOS/${_httpDev.osVersion} Device/${_httpDev.model}`;
424
423
  const bodyBuf = Buffer.from(body, 'utf8');
425
424
  const opts = {
426
425
  hostname: 'v.whatsapp.net',
@@ -463,7 +462,7 @@ async function sendRequest(path, store, waVersion, useToken, extraPairs) {
463
462
  // ---------- Public API ----------
464
463
 
465
464
  async function checkIfRegistered(store) {
466
- const waVersion = await fetchWaVersion(getDeviceConfig());
465
+ const waVersion = await fetchWaVersion();
467
466
  return sendRequest('/exist', store, waVersion, false, null);
468
467
  }
469
468
 
@@ -492,13 +491,9 @@ async function checkNumberStatus(phoneNumber) {
492
491
 
493
492
  phoneNumber = String(phoneNumber).replace(/\D/g, '');
494
493
  const store = createNewStore(phoneNumber);
495
- const waVersion = await fetchWaVersion(getDeviceConfig());
496
- const { cc } = parsePhone(phoneNumber);
497
- const meta = getCountryMeta(cc);
494
+ const waVersion = await fetchWaVersion();
498
495
 
499
496
  const baseExtra = [
500
- 'sim_mcc', meta.mcc,
501
- 'sim_mnc', meta.mnc,
502
497
  'reason', '',
503
498
  'cellular_strength', '1'
504
499
  ];
@@ -594,7 +589,7 @@ async function assertRegistrationKeys(store, waVersion) {
594
589
  async function requestSmsCode(store, method) {
595
590
  method = method || 'sms';
596
591
  const _device = getDeviceConfig();
597
- const waVersion = await fetchWaVersion(_device);
592
+ const waVersion = await fetchWaVersion();
598
593
  store.version = waVersion;
599
594
  store.device = _device;
600
595
 
@@ -606,8 +601,6 @@ async function requestSmsCode(store, method) {
606
601
  async function _tryMethod(m) {
607
602
  const extra = [
608
603
  'method', m,
609
- 'sim_mcc', '000',
610
- 'sim_mnc', '000',
611
604
  'reason', '',
612
605
  'cellular_strength', '1'
613
606
  ];
@@ -683,7 +676,7 @@ async function requestSmsCode(store, method) {
683
676
 
684
677
  async function verifyCode(store, code) {
685
678
  const _device = getDeviceConfig();
686
- const waVersion = await fetchWaVersion(_device);
679
+ const waVersion = await fetchWaVersion();
687
680
  store.version = waVersion;
688
681
  store.device = _device;
689
682
  const normalized = code.replace(/[\s\-]/g, '').replace(/\D/g, '');
@@ -708,4 +701,4 @@ async function verifyCode(store, code) {
708
701
  throw new Error(`Verification failed: ${reason || JSON.stringify(result)}`);
709
702
  }
710
703
 
711
- module.exports = { checkIfRegistered, checkNumberStatus, requestSmsCode, verifyCode, fetchIosVersion, fetchAndroidVersion, fetchWaVersion, parsePhone, assertRegistrationKeys };
704
+ module.exports = { checkIfRegistered, checkNumberStatus, requestSmsCode, verifyCode, fetchIosVersion, fetchWaVersion, parsePhone, getCountryMeta, assertRegistrationKeys };
package/lib/Store.js CHANGED
@@ -5,7 +5,7 @@ const path = require('path');
5
5
  const crypto = require('crypto');
6
6
  const curveJs = require('curve25519-js');
7
7
  const { v4: uuidv4 } = require('uuid');
8
- const { IOS_DEVICE, IOS_VERSION_FALLBACK, ANDROID_VERSION_FALLBACK } = require('./constants');
8
+ const { IOS_DEVICE, IOS_VERSION_FALLBACK } = require('./constants');
9
9
  const { getDeviceConfig } = require('./DeviceConfig');
10
10
 
11
11
  // ─────────────────────────────────────────────────────────
@@ -60,7 +60,7 @@ function createNewStore(phoneNumber) {
60
60
  const identityId = crypto.randomBytes(16);
61
61
 
62
62
  const device = getDeviceConfig();
63
- const version = device.os === 'android' ? ANDROID_VERSION_FALLBACK : IOS_VERSION_FALLBACK;
63
+ const version = IOS_VERSION_FALLBACK;
64
64
 
65
65
  return {
66
66
  phoneNumber: String(phoneNumber).replace(/^\+/, ''),
package/lib/constants.js CHANGED
@@ -7,18 +7,16 @@ const REGISTRATION_PUBLIC_KEY = Buffer.from('8e8c0f74c3ebc5d7a6865c6c3c843856b06
7
7
 
8
8
  const MOBILE_PROLOGUE = Buffer.from([0x57, 0x41, 0x05, 0x03]);
9
9
 
10
- // Static tokens used in WhatsApp registration token computation.
11
- // token = MD5( staticToken + MD5hex(waVersion) + nationalNumber )
10
+ // iOS static tokens (MD5 approach): token = MD5( staticToken + MD5hex(waVersion) + nationalNumber )
12
11
  const IOS_STATIC_TOKEN = '0a1mLfGUIBVrMKF1RdvLI5lkRBvof6vn0fD2QRSM';
13
12
  const IOS_BUSINESS_STATIC_TOKEN = 'USUDuDYDeQhY4RF2fCSp5m3F6kJ1M2J8wS7bbNA2';
14
- const ANDROID_STATIC_TOKEN = 'Y29Cs6AVNR2bj5PBeKSYFd1nAKuvNQ3h';
15
13
 
16
- // WhatsApp version fallbacks — used when live fetch fails.
17
- const IOS_VERSION_FALLBACK = '2.26.9.75';
18
- const ANDROID_VERSION_FALLBACK = '2.24.13.80';
14
+ // WhatsApp version fallback — used when ALL live iTunes sources fail.
15
+ // Updated: 2025-03. The library always tries the App Store first.
16
+ const IOS_VERSION_FALLBACK = '2.26.10.74';
19
17
 
20
18
  // Safari UA for the iTunes lookup only.
21
- const IOS_USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1';
19
+ const IOS_USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Mobile/15E148 Safari/604.1';
22
20
 
23
21
  // Default iOS device (iPhone 15 Pro, iOS 17.4.1).
24
22
  // platform 1 = iOS in WhatsApp's ClientPayload.UserAgent proto enum.
@@ -34,139 +32,129 @@ const IOS_DEVICE = {
34
32
  };
35
33
 
36
34
  // ─── iOS device profiles ───────────────────────────────────────────────────
37
- // Set WA_OS=ios WA_DEVICE=<key> in .env to select one.
35
+ // Set WA_DEVICE=<key> in .env to select one.
36
+ // When no profile is set, the library picks one at random for each new session.
37
+ // platform 1 = IOS in WhatsApp's ClientPayload.UserAgent proto enum.
38
38
  const IOS_DEVICE_PROFILES = {
39
+ 'iphone16promax': {
40
+ os: 'ios', platform: 1,
41
+ model: 'iPhone 16 Pro Max', manufacturer: 'Apple',
42
+ osVersion: '18.3.2', osBuildNumber: '22D82',
43
+ modelId: 'iPhone17,2', deviceModelType: 2
44
+ },
45
+ 'iphone16pro': {
46
+ os: 'ios', platform: 1,
47
+ model: 'iPhone 16 Pro', manufacturer: 'Apple',
48
+ osVersion: '18.3.2', osBuildNumber: '22D82',
49
+ modelId: 'iPhone17,1', deviceModelType: 2
50
+ },
51
+ 'iphone16plus': {
52
+ os: 'ios', platform: 1,
53
+ model: 'iPhone 16 Plus', manufacturer: 'Apple',
54
+ osVersion: '18.3.2', osBuildNumber: '22D82',
55
+ modelId: 'iPhone17,4', deviceModelType: 2
56
+ },
57
+ 'iphone16': {
58
+ os: 'ios', platform: 1,
59
+ model: 'iPhone 16', manufacturer: 'Apple',
60
+ osVersion: '18.3.2', osBuildNumber: '22D82',
61
+ modelId: 'iPhone17,3', deviceModelType: 2
62
+ },
63
+ 'iphone15promax': {
64
+ os: 'ios', platform: 1,
65
+ model: 'iPhone 15 Pro Max', manufacturer: 'Apple',
66
+ osVersion: '18.3.2', osBuildNumber: '22D82',
67
+ modelId: 'iPhone16,2', deviceModelType: 2
68
+ },
39
69
  'iphone15pro': {
40
70
  os: 'ios', platform: 1,
41
71
  model: 'iPhone 15 Pro', manufacturer: 'Apple',
42
- osVersion: '17.4.1', osBuildNumber: '21E236',
72
+ osVersion: '18.3.2', osBuildNumber: '22D82',
43
73
  modelId: 'iPhone16,1', deviceModelType: 2
44
74
  },
75
+ 'iphone15plus': {
76
+ os: 'ios', platform: 1,
77
+ model: 'iPhone 15 Plus', manufacturer: 'Apple',
78
+ osVersion: '18.3.2', osBuildNumber: '22D82',
79
+ modelId: 'iPhone15,5', deviceModelType: 2
80
+ },
45
81
  'iphone15': {
46
82
  os: 'ios', platform: 1,
47
83
  model: 'iPhone 15', manufacturer: 'Apple',
48
- osVersion: '17.4.1', osBuildNumber: '21E236',
84
+ osVersion: '18.3.2', osBuildNumber: '22D82',
49
85
  modelId: 'iPhone15,4', deviceModelType: 2
50
86
  },
51
- 'iphone14': {
87
+ 'iphone14promax': {
52
88
  os: 'ios', platform: 1,
53
- model: 'iPhone 14', manufacturer: 'Apple',
54
- osVersion: '17.4.1', osBuildNumber: '21E236',
55
- modelId: 'iPhone14,2', deviceModelType: 2
89
+ model: 'iPhone 14 Pro Max', manufacturer: 'Apple',
90
+ osVersion: '18.3.2', osBuildNumber: '22D82',
91
+ modelId: 'iPhone15,3', deviceModelType: 2
56
92
  },
57
93
  'iphone14pro': {
58
94
  os: 'ios', platform: 1,
59
95
  model: 'iPhone 14 Pro', manufacturer: 'Apple',
60
- osVersion: '17.4.1', osBuildNumber: '21E236',
96
+ osVersion: '18.3.2', osBuildNumber: '22D82',
61
97
  modelId: 'iPhone15,2', deviceModelType: 2
62
98
  },
99
+ 'iphone14plus': {
100
+ os: 'ios', platform: 1,
101
+ model: 'iPhone 14 Plus', manufacturer: 'Apple',
102
+ osVersion: '17.7.5', osBuildNumber: '21H516',
103
+ modelId: 'iPhone14,8', deviceModelType: 2
104
+ },
105
+ 'iphone14': {
106
+ os: 'ios', platform: 1,
107
+ model: 'iPhone 14', manufacturer: 'Apple',
108
+ osVersion: '17.7.5', osBuildNumber: '21H516',
109
+ modelId: 'iPhone14,7', deviceModelType: 2
110
+ },
111
+ 'iphone13pro': {
112
+ os: 'ios', platform: 1,
113
+ model: 'iPhone 13 Pro', manufacturer: 'Apple',
114
+ osVersion: '17.7.5', osBuildNumber: '21H516',
115
+ modelId: 'iPhone14,2', deviceModelType: 2
116
+ },
63
117
  'iphone13': {
64
118
  os: 'ios', platform: 1,
65
119
  model: 'iPhone 13', manufacturer: 'Apple',
66
- osVersion: '16.7.8', osBuildNumber: '20H343',
120
+ osVersion: '17.7.5', osBuildNumber: '21H516',
67
121
  modelId: 'iPhone14,5', deviceModelType: 2
68
122
  },
123
+ 'iphone12pro': {
124
+ os: 'ios', platform: 1,
125
+ model: 'iPhone 12 Pro', manufacturer: 'Apple',
126
+ osVersion: '17.7.5', osBuildNumber: '21H516',
127
+ modelId: 'iPhone13,3', deviceModelType: 1
128
+ },
69
129
  'iphone12': {
70
130
  os: 'ios', platform: 1,
71
131
  model: 'iPhone 12', manufacturer: 'Apple',
72
- osVersion: '15.8.3', osBuildNumber: '19H384',
132
+ osVersion: '17.7.5', osBuildNumber: '21H516',
73
133
  modelId: 'iPhone13,2', deviceModelType: 1
74
- }
75
- };
76
-
77
- // ─── Android device profiles ───────────────────────────────────────────────
78
- // Set WA_OS=android WA_DEVICE=<key> in .env to select one.
79
- // platform 3 = ANDROID in WhatsApp's ClientPayload.UserAgent proto enum.
80
- const ANDROID_DEVICE_PROFILES = {
81
- 'samsung-s24-ultra': {
82
- os: 'android', platform: 3,
83
- model: 'Samsung Galaxy S24 Ultra', manufacturer: 'Samsung',
84
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
85
- modelId: 'SM-S928B', deviceModelType: 2
86
- },
87
- 'samsung-s24': {
88
- os: 'android', platform: 3,
89
- model: 'Samsung Galaxy S24', manufacturer: 'Samsung',
90
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
91
- modelId: 'SM-S921B', deviceModelType: 2
92
- },
93
- 'samsung-s23': {
94
- os: 'android', platform: 3,
95
- model: 'Samsung Galaxy S23', manufacturer: 'Samsung',
96
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
97
- modelId: 'SM-S911B', deviceModelType: 2
98
- },
99
- 'samsung-s23-ultra': {
100
- os: 'android', platform: 3,
101
- model: 'Samsung Galaxy S23 Ultra', manufacturer: 'Samsung',
102
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
103
- modelId: 'SM-S918B', deviceModelType: 2
104
- },
105
- 'samsung-a55': {
106
- os: 'android', platform: 3,
107
- model: 'Samsung Galaxy A55', manufacturer: 'Samsung',
108
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
109
- modelId: 'SM-A556B', deviceModelType: 1
110
- },
111
- 'pixel8pro': {
112
- os: 'android', platform: 3,
113
- model: 'Pixel 8 Pro', manufacturer: 'Google',
114
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
115
- modelId: 'Pixel 8 Pro', deviceModelType: 2
116
- },
117
- 'pixel8': {
118
- os: 'android', platform: 3,
119
- model: 'Pixel 8', manufacturer: 'Google',
120
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
121
- modelId: 'Pixel 8', deviceModelType: 2
122
- },
123
- 'pixel7': {
124
- os: 'android', platform: 3,
125
- model: 'Pixel 7', manufacturer: 'Google',
126
- osVersion: '14', osBuildNumber: 'TP1A.221005.002',
127
- modelId: 'Pixel 7', deviceModelType: 2
128
- },
129
- 'pixel7a': {
130
- os: 'android', platform: 3,
131
- model: 'Pixel 7a', manufacturer: 'Google',
132
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
133
- modelId: 'Pixel 7a', deviceModelType: 1
134
- },
135
- 'xiaomi14': {
136
- os: 'android', platform: 3,
137
- model: 'Xiaomi 14', manufacturer: 'Xiaomi',
138
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
139
- modelId: '23127PN0CG', deviceModelType: 2
140
- },
141
- 'xiaomi13': {
142
- os: 'android', platform: 3,
143
- model: 'Xiaomi 13', manufacturer: 'Xiaomi',
144
- osVersion: '13', osBuildNumber: 'TQ3A.230901.001',
145
- modelId: '2211133G', deviceModelType: 2
146
- },
147
- 'oneplus12': {
148
- os: 'android', platform: 3,
149
- model: 'OnePlus 12', manufacturer: 'OnePlus',
150
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
151
- modelId: 'CPH2573', deviceModelType: 2
152
- },
153
- 'oneplus11': {
154
- os: 'android', platform: 3,
155
- model: 'OnePlus 11', manufacturer: 'OnePlus',
156
- osVersion: '13', osBuildNumber: 'TQ3A.230901.001',
157
- modelId: 'CPH2449', deviceModelType: 2
158
- },
159
- 'oppo-find-x7': {
160
- os: 'android', platform: 3,
161
- model: 'OPPO Find X7', manufacturer: 'OPPO',
162
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
163
- modelId: 'CPH2599', deviceModelType: 2
164
- },
165
- 'realme-gt5': {
166
- os: 'android', platform: 3,
167
- model: 'realme GT 5 Pro', manufacturer: 'realme',
168
- osVersion: '14', osBuildNumber: 'UP1A.231005.007',
169
- modelId: 'RMX3888', deviceModelType: 2
134
+ },
135
+ 'iphonese3': {
136
+ os: 'ios', platform: 1,
137
+ model: 'iPhone SE (3rd generation)', manufacturer: 'Apple',
138
+ osVersion: '17.7.5', osBuildNumber: '21H516',
139
+ modelId: 'iPhone14,6', deviceModelType: 1
140
+ },
141
+ 'iphone11pro': {
142
+ os: 'ios', platform: 1,
143
+ model: 'iPhone 11 Pro', manufacturer: 'Apple',
144
+ osVersion: '17.7.5', osBuildNumber: '21H516',
145
+ modelId: 'iPhone12,3', deviceModelType: 1
146
+ },
147
+ 'iphone11': {
148
+ os: 'ios', platform: 1,
149
+ model: 'iPhone 11', manufacturer: 'Apple',
150
+ osVersion: '17.7.5', osBuildNumber: '21H516',
151
+ modelId: 'iPhone12,1', deviceModelType: 1
152
+ },
153
+ 'iphonexs': {
154
+ os: 'ios', platform: 1,
155
+ model: 'iPhone Xs', manufacturer: 'Apple',
156
+ osVersion: '16.7.11', osBuildNumber: '20H330',
157
+ modelId: 'iPhone11,2', deviceModelType: 1
170
158
  }
171
159
  };
172
160
 
@@ -199,13 +187,10 @@ module.exports = {
199
187
  MOBILE_PROLOGUE,
200
188
  IOS_STATIC_TOKEN,
201
189
  IOS_BUSINESS_STATIC_TOKEN,
202
- ANDROID_STATIC_TOKEN,
203
190
  IOS_VERSION_FALLBACK,
204
- ANDROID_VERSION_FALLBACK,
205
191
  IOS_USER_AGENT,
206
192
  IOS_DEVICE,
207
193
  IOS_DEVICE_PROFILES,
208
- ANDROID_DEVICE_PROFILES,
209
194
  SIGNAL_KEY_TYPE,
210
195
  RELEASE_CHANNEL,
211
196
  TAG
package/lib/noise.js CHANGED
@@ -9,6 +9,7 @@ const { hkdf } = require('@noble/hashes/hkdf');
9
9
  const { MOBILE_PROLOGUE, WHATSAPP_HOST, WHATSAPP_PORT } = require('./constants');
10
10
  const { encodeHandshakeClientHello, encodeHandshakeClientFinish,
11
11
  decodeServerHello, encodeClientPayload } = require('./proto');
12
+ const { parsePhone, getCountryMeta } = require('./Registration');
12
13
 
13
14
  // ─── CertChain validator ────────
14
15
  //
@@ -282,6 +283,8 @@ class NoiseSocket extends EventEmitter {
282
283
  const sharedSS = dhShared(noisePriv, serverHello.ephemeral);
283
284
  this.noiseState.mixKey(sharedSS);
284
285
 
286
+ const { cc: _cc } = parsePhone(this.store.phoneNumber);
287
+ const _meta = getCountryMeta(_cc);
285
288
  const payload = encodeClientPayload({
286
289
  username: BigInt(this.store.phoneNumber),
287
290
  passive: false,
@@ -293,18 +296,18 @@ class NoiseSocket extends EventEmitter {
293
296
  device: 0,
294
297
  oc: false,
295
298
  userAgent: {
296
- platform: (this.store.device && this.store.device.platform) || 1,
299
+ platform: 1,
297
300
  version: this.store.version,
298
- mcc: '000',
299
- mnc: '000',
301
+ mcc: _meta.mcc,
302
+ mnc: _meta.mnc,
300
303
  osVersion: this.store.device.osVersion,
301
304
  manufacturer: this.store.device.manufacturer,
302
305
  device: this.store.device.model,
303
306
  osBuildNumber: this.store.device.osBuildNumber,
304
307
  phoneId: this.store.fdid.toUpperCase(),
305
308
  releaseChannel: 0,
306
- localeLanguage: 'en',
307
- localeCountry: 'US',
309
+ localeLanguage: _meta.lg || 'en',
310
+ localeCountry: _meta.lc || 'US',
308
311
  deviceType: 0,
309
312
  deviceModelType: this.store.device.modelId
310
313
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whalibmob",
3
- "version": "5.1.16",
3
+ "version": "5.1.17",
4
4
  "description": "WhatsApp library for interaction with WhatsApp Mobile API no web",
5
5
  "author": "Kunboruto20",
6
6
  "main": "index.js",