- Python 100%
- viewstats_api.py: Full API client with AES-256-GCM decryption for 19 endpoints (dashboard, outliers, browse, alerts, thumbnails, competitors, A/B tests, auth) - explore.py: Automated endpoint explorer that dumps request docs + decoded responses - capture_screenshots.py: Playwright-based screenshot capture with modal dismissal - docs/: Per-endpoint request.md, response.json, and UI screenshots - docs/README.md: Auth flow, encryption scheme, base URL routing, endpoint index Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| docs | ||
| .gitignore | ||
| .python-version | ||
| capture_screenshots.py | ||
| explore.py | ||
| main.py | ||
| pyproject.toml | ||
| uv.lock | ||
| viewstats_api.py | ||
Viewstats API Documentation
Reverse-engineered documentation for the Viewstats API.
Authentication
Login
POST https://auth.viewstats.com/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "...",
"type": "email_password"
}
Returns { "success": true, "token": "eyJhbGciOiJFZERTQSJ9..." }.
The token is a JWT (EdDSA-signed). Pass it as Authorization: Bearer <token> on all subsequent requests.
Note: The "type": "email_password" field is required — omitting it returns {"reason": "TYPE_IS_REQUIRED", "success": false}.
Other Auth Methods
POST auth.viewstats.com/login/apple— Apple Sign-InGET auth.viewstats.com/login— Google OAuth redirect
Anonymous Token
When no auth cookie exists, the JS bundle uses a hardcoded fallback token:
32ev9m0qggn227ng1rgpbv5j8qllas8uleujji3499g9had6oj7f0ltnvrgi00cq
Response Encryption (AES-256-GCM)
Most API responses are encrypted with AES-256-GCM. The key and IV are hardcoded in the client JS bundle (chunk 56002-a10e018f0b0dc73e.js, module 54708).
- Content-Type:
application/octet-stream→ encrypted, needs decryption - Content-Type:
application/json→ plain JSON, no decryption needed
Key Material
Stored as base64-encoded JSON arrays of signed bytes:
Key (base64): Wy0zLCAtMTEyLCAxNSwgLTEyNCwgLTcxLCAzMywgLTg0LCAxMDksIDU3LCAtMTI3LCAxMDcsIC00NiwgMTIyLCA0OCwgODIsIC0xMjYsIDQ3LCA3NiwgLTEyNywgNjUsIDc1LCAxMTMsIC0xMjEsIDg5LCAtNzEsIDUwLCAtODMsIDg2LCA5MiwgLTQ2LCA0OSwgNTZd
IV (base64): Wzk3LCAxMDksIC0xMDAsIC05MCwgMTIyLCAtMTI0LCAxMSwgLTY5LCAtNDIsIDExNSwgLTU4LCAtNjcsIDQzLCAtNzUsIDMxLCA3NF0=
Decoding: base64 → UTF-8 string → JSON.parse → Uint8Array (negatives wrap via & 0xFF)
- Key: 32 bytes (AES-256)
- IV: 16 bytes (static — this is obfuscation, not real per-request security)
Python Decryption
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import base64, json
def _decode_signed_bytes(b64):
signed = json.loads(base64.b64decode(b64).decode("utf-8"))
return bytes(b & 0xFF for b in signed)
KEY = _decode_signed_bytes("<key_b64>")
IV = _decode_signed_bytes("<iv_b64>")
def decrypt_response(ciphertext: bytes) -> dict:
aesgcm = AESGCM(KEY)
plaintext = aesgcm.decrypt(IV, ciphertext, None)
return json.loads(plaintext.decode("utf-8"))
Base URLs
| Purpose | URL |
|---|---|
| Direct backend API | https://api.viewstats.com |
| Next.js API routes | https://www.viewstats.com |
| Auth | https://auth.viewstats.com |
| Payment | https://payment.viewstats.com |
Routing rule: Endpoints starting with /api/ are Next.js API routes served by www.viewstats.com. All other data endpoints (/channels/, /outliers/, /competitors/, /thumbnail/, /alerts/) go to api.viewstats.com.
For /api/ routes, the auth token must also be set as a VS_AUTH cookie on .viewstats.com.
Required Headers
Cloudflare requires Origin and Referer — without them, responses are garbled.
| Header | Value |
|---|---|
User-Agent |
Standard browser UA |
Origin |
https://www.viewstats.com |
Referer |
https://www.viewstats.com/ |
Authorization |
Bearer <token> |
There's also an x-Fuinjutsu: Bearer <BOT_PREVENTION_TOKEN> header used in-browser for bot-shield protection, but it's not needed for script-level access with proper headers.
Endpoint Index
Dashboard — api.viewstats.com/channels/dashboard/{channelId}/...
| Endpoint | Description | Docs |
|---|---|---|
/header |
Channel stats summary (views, subs, engagement, AVP) | dashboard/header |
/series |
Views timeline (chart, metric, breakdown, range, compare) | dashboard/series |
/subscribers/series |
Subscriber timeline (chart, range, breakdown) | dashboard/subscribers_series |
/videos |
Video list table (limit, videoSort) | dashboard/videos |
Outliers
| Endpoint | Base | Description | Docs |
|---|---|---|---|
/api/outliers |
www | Outlier search (q, limit, page, category, isShort, refresh) | outliers/search |
/outliers/search/qdrant |
api | Vector-based outlier search (q, category, isRecent, isShort, pageNumber) | outliers/qdrant |
Browse — api.viewstats.com
| Endpoint | Description | Docs |
|---|---|---|
/channels/search/advanced |
Advanced channel search | browse/channel_search |
/channels/@{handle} |
Channel details by handle | browse/channel_details |
Alerts
| Endpoint | Base | Description | Docs |
|---|---|---|---|
/alerts/tree |
api | Alert tree/list | alerts/list |
/api/alert |
www | Single alert (alertId) | — |
/api/alertVideos |
www | Videos for an alert (alertId, sortBy, type, limit) | alerts/videos |
Thumbnails — api.viewstats.com
| Endpoint | Description | Docs |
|---|---|---|
/thumbnail/search/test |
AI thumbnail search (q, limit, youtubeUrl) | thumbnails/search |
/api/uploadImage |
Upload image for search | — |
/api/videoById |
Video details (videoId) | — |
Competitors
| Endpoint | Base | Description | Docs |
|---|---|---|---|
/competitors/channels |
api | Competitor channel list | competitors/channels |
/api/competitors/feed |
www | Competitor activity feed | competitors/feed |
A/B Tests — www.viewstats.com
| Endpoint | Description | Docs |
|---|---|---|
/api/abTesting/byVideo |
A/B tests by video (query, sortBy, categoryId, limit) | ab_tests/by_video |
/api/abTesting/byChannel |
A/B tests by channel (channelHandle) | ab_tests/by_channel |
/api/abTesting/channelSearch |
Search channels for A/B tests (query) | — |
/api/youtubeCategories |
YouTube category list | ab_tests/categories |
Account / Payment — www.viewstats.com
| Endpoint | Description | Docs |
|---|---|---|
/api/auth/invoices |
Billing invoices | auth/invoices |
/api/payment/prices |
Subscription pricing | auth/prices |
/api/status |
Account/service status | auth/status |
/api/channelById |
Channel info (channelHandle) | — |
JS Bundle Sources
Key Next.js chunk files containing endpoint definitions:
| Chunk | Content |
|---|---|
56002-a10e018f0b0dc73e.js |
Decryption logic (modules 54708, 29112, 69777, 67018) |
app/pro/dashboard/page-c2177666518f6f4b.js |
Dashboard endpoints |
30120-13ec7778ccb7b577.js |
Route definitions |
25277-d56382b781da9da6.js |
Payment/Paddle/invoice endpoints |