curl --request POST \
--url 'https://api.simkl.com/users/{user_id}/stats?client_id=' \
--header 'Content-Type: application/json' \
--header 'User-Agent: <user-agent>' \
--data '{}'{
"total_mins": 908554,
"movies": {
"total_mins": 171969,
"plantowatch": {
"mins": 18938,
"count": 173
},
"completed": {
"mins": 171852,
"count": 1558
}
},
"tv": {
"total_mins": 242560,
"watching": {
"watched_episodes_count": 2612,
"count": 41,
"left_to_watch_episodes": 10276,
"left_to_watch_mins": 411040,
"total_episodes_count": 12888
},
"hold": {
"watched_episodes_count": 1157,
"count": 41,
"left_to_watch_episodes": 828,
"left_to_watch_mins": 33120,
"total_episodes_count": 1985
},
"plantowatch": {
"watched_episodes_count": 243,
"count": 118,
"left_to_watch_episodes": 12961,
"left_to_watch_mins": 518440,
"total_episodes_count": 13204
},
"completed": {
"watched_episodes_count": 2111,
"count": 55
}
},
"anime": {
"total_mins": 494025,
"watching": {
"watched_episodes_count": 1747,
"count": 21,
"left_to_watch_episodes": 410,
"left_to_watch_mins": 10250,
"total_episodes_count": 2157
},
"hold": {
"watched_episodes_count": 97,
"count": 23,
"left_to_watch_episodes": 462,
"left_to_watch_mins": 11550,
"total_episodes_count": 559
},
"plantowatch": {
"watched_episodes_count": 2324,
"count": 719,
"left_to_watch_episodes": 7829,
"left_to_watch_mins": 195725,
"total_episodes_count": 10153
},
"completed": {
"watched_episodes_count": 17255,
"count": 1291
}
},
"watched_last_week": {
"total_mins": 130,
"movies_mins": 130,
"tv_mins": 0,
"anime_mins": 0
}
}The most expensive call in the Simkl API. Only fire it on an explicit user action.
Stats are computed live on every request — there is no edge cache and no precomputed result cache. The server walks the user’s entire watch history across all three catalogs (movies, TV, anime), looks up the runtime of every completed episode and movie, and aggregates everything from scratch. Response time scales with the size of the user’s library.
OK to call: when the user opens a “My stats” / “Year in review” / profile screen, or taps a refresh button on a stats widget.
Do not call: on app launch, on resume from background, in any polling loop, speculatively to “warm” data, or for every user in a list (e.g. a friends leaderboard — batch via lazy loading). Apps that hammer this endpoint risk rate-limit throttling on the client_id.
Returns aggregate stats for the given user — total movies / shows / anime watched, total time spent, episode counts, last-week activity, and basic profile info.
The user_id must be a positive integer — the numeric Simkl id of the target account. To fetch stats for the authenticated user, call POST /users/settings once at app start and cache account.id, then pass that value here.
Public profiles can be fetched without a bearer token (clientId-only). Private profiles require either a bearer token belonging to the target user, or a connection the target user has granted the requester (otherwise 403 private_profile).
This is POST for historical reasons — there is no request body.
{
"user": {
"id": 51,
"name": "username",
"joined_at": "2018-01-15T00:00:00Z",
"avatar": "https://simkl.in/avatars/.../user_100.jpg",
"gender": "Male",
"loc": "Spain",
"age": 28,
"type": "vip"
},
"total_mins": 78230,
"movies": {
"total_mins": 18000,
"plantowatch": { "mins": 0, "count": 12 },
"completed": { "mins": 18000, "count": 200 },
"dropped": { "mins": 0, "count": 1 }
},
"tv": {
"total_mins": 35000,
"watching": { "watched_episodes_count": 23, "count": 4, "left_to_watch_episodes": 12, "left_to_watch_mins": 600, "total_episodes_count": 35 }
},
"anime": {... },
"watched_last_week": { "total_mins": 320, "movies_mins": 60, "tv_mins": 200, "anime_mins": 60 }
}
The user block is omitted when the target user has not loaded any data (e.g. brand-new accounts); only total_mins and the per-domain blocks are guaranteed.
| Code | When |
|---|---|
404 user_id_failed | user_id is 0 or any non-positive integer. There is no shortcut for the authenticated user — always pass a real numeric id. |
403 private_profile | The target user’s profile is private and the requester does not have access. |
curl --request POST \
--url 'https://api.simkl.com/users/{user_id}/stats?client_id=' \
--header 'Content-Type: application/json' \
--header 'User-Agent: <user-agent>' \
--data '{}'{
"total_mins": 908554,
"movies": {
"total_mins": 171969,
"plantowatch": {
"mins": 18938,
"count": 173
},
"completed": {
"mins": 171852,
"count": 1558
}
},
"tv": {
"total_mins": 242560,
"watching": {
"watched_episodes_count": 2612,
"count": 41,
"left_to_watch_episodes": 10276,
"left_to_watch_mins": 411040,
"total_episodes_count": 12888
},
"hold": {
"watched_episodes_count": 1157,
"count": 41,
"left_to_watch_episodes": 828,
"left_to_watch_mins": 33120,
"total_episodes_count": 1985
},
"plantowatch": {
"watched_episodes_count": 243,
"count": 118,
"left_to_watch_episodes": 12961,
"left_to_watch_mins": 518440,
"total_episodes_count": 13204
},
"completed": {
"watched_episodes_count": 2111,
"count": 55
}
},
"anime": {
"total_mins": 494025,
"watching": {
"watched_episodes_count": 1747,
"count": 21,
"left_to_watch_episodes": 410,
"left_to_watch_mins": 10250,
"total_episodes_count": 2157
},
"hold": {
"watched_episodes_count": 97,
"count": 23,
"left_to_watch_episodes": 462,
"left_to_watch_mins": 11550,
"total_episodes_count": 559
},
"plantowatch": {
"watched_episodes_count": 2324,
"count": 719,
"left_to_watch_episodes": 7829,
"left_to_watch_mins": 195725,
"total_episodes_count": 10153
},
"completed": {
"watched_episodes_count": 17255,
"count": 1291
}
},
"watched_last_week": {
"total_mins": 130,
"movies_mins": 130,
"tv_mins": 0,
"anime_mins": 0
}
}Documentation Index
Fetch the complete documentation index at: https://api.simkl.org/llms.txt
Use this file to discover all available pages before exploring further.
Preferred form: your client_id as a URL query parameter on every request. Self-describing in logs and curl commands. See Headers and required parameters.
Descriptive identifier for your app, ideally name/version. Examples: PlexMediaServer/1.43.1.10540, kodi-simkl/0.9.2, MyApp/2.4.1 (https://myapp.com).
Target user's numeric Simkl id (positive integer). For the authenticated user, first call POST /users/settings and pass back account.id. Passing 0 returns 404 user_id_failed.
x >= 1Your client_id from your Simkl developer settings. Required on every request.
Short, lowercase identifier for your app (e.g. plex-scrobbler, kodi-bridge). Helps Simkl identify which apps are using the API.
Your app's current version (e.g. 1.0, 2.4.1). Helps Simkl debug issues you report.
OK
Aggregate watch statistics for a user.
Hide child attributes
Type 4 null — data not on file in that field's slot. See Null and missing values.
Age in years, pre-formatted as a string like "30 years". Empty string if the user has not set their birthday or has disabled age display. Pre-formatted by the server — clients should display verbatim rather than parsing.
"30 years"
Simkl account plan tier. free is the default; pro and vip are paid tiers that unlock higher rate limits and additional features. Some endpoints gate behavior on this value.
free, pro, vip Total minutes watched across movies, TV, and anime.
Was this page helpful?