ScratchDB is an API for data from scratch.mit.edu. All of the data was collected using information from ScratchIndexer v2, with some extra help from ScratchStats
The content on this website is free to use, as long as you abide by the license outlined at the bottom of the page.
Support is available at my profile here, I can only provide support for this API and ScratchIndexer.
The ScratchDB API is built to return as much information as possible in one request, with many different options for organization.
This API can change at any time with little warning, but generally the only changes will new endpoints or new data on an endpoint.
Most queries will have a query_time
added to the end. This represents how long a request took in milliseconds, from the time it was created to the time it was served.
Most queries will also have a wid
added to the end. This represents which system processed the request. If the request never accesses a cached database this will not be defined. This value changes each time the cache is refreshed
Most queries will also have a revision
added to the end. This represents the current version of the system. If you plan on using this, I recommend making sure your code still works with each revision.
This endpoint is used to get information about a specific user
Usage: /v2/user/info/[username]
Example response:
{
{
"username": "World_Languages",
"id": 4648559,
"sys_id": 745,
"joined": "2014-08-31T00:00:00.000Z",
"followers": 8366,
"following": 177,
"country": "Argentina",
"bio": "<br> ✌️ ᴡᴏʀʟᴅ_ʟᴀɴɢᴜᴀɢᴇs ✌️<br><br> ⭐️ sᴄʀᴀᴛᴄʜ ʜᴀᴄᴋs & ᴛᴏᴏʟs ⭐️<br><br><br>Alt account: <a href=\"/users/Earth_Languages\">@Earth_Languages</a>",
"work": "⚙️ Check out my Scratch websites ⚙️<br>⚡️ ScratchStats.com - many statistics about any scratcher, most followed scratchers ranking, most popular projects list, and more!<br>✉️ ScratchNotifier.cf - get browser notifications<br>when you get new Scratch messages",
"status": "Scratcher",
"school": null,
"statistics": {
"ranks": {
"country": {
"views": 1,
"loves": 1,
"comments": 1,
"favorites": 1,
"followers": 1,
"following": 33
},
"views": 754,
"loves": 255,
"comments": 40,
"favorites": 250,
"followers": 41,
"following": 18869
},
"views": 188540,
"loves": 16051,
"comments": 52715,
"favorites": 12854,
"followers": 8366,
"following": 177
},
"query_time": 2,
"wid": "407fe8f",
"revision": "f67190d"
}
}
The data returned is an object with the following content:
Key | Value | Example | Description |
---|---|---|---|
username |
String | World_Languages |
The username of the user |
id |
Integer | 4648559 |
The Scratch ID of the user |
sys_id |
Integer | 745 |
The ID generated by ScratchDB, missing numbers exist |
joined |
Date | 2014-08-31T00:00:00.000Z |
The date a user a joined. The time is set to 0, this is not exact |
followers |
Integer | 8366 |
The number of followers a user had the last time the system checked |
following |
Integer | 177 |
The number of people a user was following the last time the system checked |
country |
String | Argentina |
The country a user is in. This value may be equal to a nonexistent country, like AT or "Location not given" |
bio |
String | The bio of a user, HTML format | |
work |
String | The What I'm Working On of a user, HTML format | |
status |
String | Scratcher |
What rank a user is, New, Scratcher, ST, etc |
school |
Integer | 23422 |
The ID of a school, if a user is in one |
query_time |
Integer | 1 |
The time in milliseconds the request took to process in the backend |
revision |
String | f67190d |
The current commit ID |
wid |
String | 407fe8f |
the worker cache ID |
statistics |
Object | described below | generated statistics of a user |
Key | Value | Example | Description |
---|---|---|---|
loves |
Integer | 16051 |
Number of favorites on all of the found user's projects |
favorites |
Integer | 12854 |
Number of favorites on all of the found user's projects |
views |
Integer | 188540 |
Number of views on all of the found user's projects |
comments |
Integer | 52715 |
Number of comments on all of the found user's projects |
followers |
Integer | 8366 |
Number of followers a user had since the last time a user was checked, may be different from the value explained above |
following |
Integer | 177 |
Number of followers a user had since the last time a user was checked, may be different from the value explained above |
ranks |
Object | described below | generated ranks of a user |
Key | Value | Example | Description |
---|---|---|---|
followers |
Integer | 41 |
Rank globally of how many followers the user has |
following |
Integer | 18869 |
Rank globally of how many people the user follows |
loves |
Integer | 255 |
Rank globally of how many loves the user has on their projects |
views |
Integer | 754 |
Rank globally of how many views the user has on their projects |
comments |
Integer | 40 |
Rank globally of how many comments the user has on their projects |
favorites |
Integer | 47 |
Rank globally of how many favorites the user has on their projects |
country |
Object | Contains the same statistics above, but on the level of the user's country, instead of globally |
Note: Students and teachers are only included in this endpoint if they have more than 1000 total views
This endpoint is used to get a list of up to 100 users at a time of their positions in the rank lists
Possible lists are: views, loves, comments, favorites, followers, following
It is possible to get these lists on a global or per-country list:
Usage: /v2/user/rank/[country]/[type]/[page]
country
can be either a country or global
for worldwide rankingstype
can be one of the lists stated abovepage
starts at 0, each increment of 1 will show the next 100 users. (optional)Example response: (shortened)
{
"users": [{
"ranks": {
"country": {
"views": 1,
"loves": 1,
"comments": 1,
"favorites": 1,
"followers": 1,
"following": 5879
},
"views": 1,
"loves": 1,
"comments": 1,
"favorites": 1,
"followers": 1,
"following": 76778
},
"info": {
"username": "griffpatch",
"scratch_id": 1882674,
"country": "United Kingdom",
"status": "Scratcher",
"school": null
},
"views": 76520852,
"loves": 944474,
"comments": 1035436,
"favorites": 843841,
"followers": 143772,
"following": 41
},
{
"ranks": {
"country": {
"views": 3,
"loves": 1,
"comments": 1,
"favorites": 1,
"followers": 1,
"following": 19331
},
"views": 4,
"loves": 2,
"comments": 2,
"favorites": 2,
"followers": 2,
"following": 34533
},
"info": {
"username": "Will_Wam",
"scratch_id": 3051823,
"country": "United States",
"status": "Scratcher",
"school": null
},
"views": 11254632,
"loves": 437219,
"comments": 349624,
"favorites": 373286,
"followers": 41336,
"following": 100
}...
],
"query_time": 1,
"wid": "407fe8f",
"revision": "f67190d"
}
The data is returned as an array of 100 users with the following content for each item in the array:
Key | Value | Example | Description |
---|---|---|---|
users |
Object | User information, explained below | |
query_time |
Integer | 1 |
The time in milliseconds the request took to process in the backend |
wid |
String | 407fe8f |
the worker cache ID |
revision |
String | f67190d |
The current commit ID |
This data is nearly identical to that if the data if you were to query for an individual user, but the info
object is added. This is explained below
Key | Value | Example | Description |
---|---|---|---|
username |
String | griffpatch |
The username of the user |
scratch_id |
Integer | 1882674 |
The Scratch ID of the user |
country |
Integer | United Kingdom |
The user's country |
status |
String | Scratcher |
What rank a user is, New, Scratcher, ST, etc |
school |
Integer | 3453 |
If a student, this value will be the school ID. Otherwise this is null . Teachers are null as well |
This endpoint is used to get information about a specific project
Usage /v2/project/info/id/[id]
Example response:
{
"id": 10016238,
"sys_id": 15833,
"username": "griffpatch",
"last_updated": "2020-05-04T20:34:39.000Z",
"times": {
"created": "2013-01-28T17:08:11.000Z",
"modified": "2013-01-28T22:08:11.000Z",
"shared": "2013-01-29T21:11:46.000Z"
},
"title": "Pacman HD with full Ghost AI (Scratch 2)",
"description": "Updated to use the new scratch 2 blocks for speed (still more to do there), and used clone to create the 4 ghosts using just one sprite. The moving elements of the game are now also all re-scalable vector graphics, so they look good big!\n\nThe good thing about this version of Pacman is that I have programmed the four ghosts with the real personalities that they had in the original arcade game. Each one has it's own intelligent rules which it uses to try to trap Pacman in the maze (yes, they actually work as a team!)",
"instructions": "Working on a Pacman clone :) - Don't worry about the initially blank screen - the level will load up when you click the Green Flag.\n\nUse the arrow keys to navigate - You can press the direction before you reach a turn and Pacman will attempt to turn when he reaches it.\n",
"public": 1,
"comments_allowed": 1,
"remix": {
"parent": null,
"root": null
},
"statistics": {
"ranks": {
"views": 569,
"loves": 825,
"favorites": 815,
"comments": 1517
},
"views": 153777,
"loves": 4030,
"favorites": 3319,
"comments": 2682
},
"query_time": 17,
"wid": "407fe8f",
"revision": "5d7258f"
}
The data returned is an object with the following content:
Key | Value | Example | Description |
---|---|---|---|
id |
Integer | 10016238 |
The Scratch ID of the project |
sys_id |
Integer | 15833 |
The ScratchDB ID of the project |
username |
String | griffpatch |
The username of the author of the project |
last-updated |
Timestamp | 2020-05-04T20:34:39.000Z |
The timestamp of when the project was last checked |
times |
Object | Certain project timestamps, explained below | |
title |
String | Pacman HD with full Ghost AI (Scratch 2) |
Project title |
description |
String | Project description | |
instructions |
String | Project instruction | |
public |
Integer/Boolean | 1 |
If the project is public or not, not always accurate |
comments_allowed |
Integer/Boolean | 1 |
If the project allows comments or not |
remix |
Object | {"parent": null, "root": null} |
Project's remix parent and original project IDs, if it exists |
statistics |
Object | Project statistics, explained below | |
query_time |
Integer | 17 |
Time in milliseconds to generate the page |
wid |
String | 407fe8f |
the worker cache ID |
revision |
String | 5d7258f |
The current commit ID |
Note: times may be different by a few hours depending on time zones
Key | Value | Example | Description |
---|---|---|---|
created |
Timestamp | 2013-01-28T17:08:11.000Z |
Timestamp of when the project was created |
modified |
Timestamp | 2013-01-28T22:08:11.000Z |
Timestamp of when the project was last modified |
shared |
Timestamp | 2013-01-29T21:11:46.000Z |
Timestamp of when the project was shared |
Key | Value | Example | Description |
---|---|---|---|
ranks |
Object | What position in ranks the project is, explained below | |
views |
Integer | 153777 |
Number of views the project has |
loves |
Integer | 4030 |
Number of loves the project has |
favorites |
Integer | 3319 |
Number of favorites the project has |
comments |
Integer | 2682 |
Number of comments the project has |
Note: if a project has below 100 views, or the system is not ready yet, this will not be defined
Key | Value | Example | Description |
---|---|---|---|
views |
Integer | 569 |
Rank globally how many views the project has |
loves |
Integer | 825 |
Rank globally how many loves the project has |
favorites |
Integer | 815 |
Rank globally how many favorites the project has |
comments |
Integer | 1517 |
Rank globally how many comments the project has |
This endpoint is used to get a list of up to 100 projects at a time in their rank lists
possible lists are views, loves, favorites, comments
Usage: /v2/project/rank/[type]/[page]
Example response (shortened):
{
"projects": [{
"ranks": {
"views": 1,
"loves": 1,
"favorites": 1,
"comments": 1
},
"info": {
"username": "griffpatch",
"title": "Paper Minecraft v11.5 (Minecraft 2D)",
"scratch_id": 10128407,
"sys_id": 15838
},
"views": 33098483,
"loves": 179378,
"favorites": 160806,
"comments": 143714
},
{
"ranks": {
"views": 2,
"loves": 2,
"favorites": 2,
"comments": 2
},
"info": {
"username": "griffpatch",
"title": "Geometry Dash v1.5",
"scratch_id": 105500895,
"sys_id": 15901
},
"views": 23599803,
"loves": 124566,
"favorites": 109738,
"comments": 103931
}
],
"query_time": 23,
"wid": "407fe8f",
"revision": "5d7258f"
}
The data returned is an array of 100 users, the base has the following:
Key | Value | Example | Description |
---|---|---|---|
projects |
Object | Project information, explained below | |
query_time |
Integer | 1 |
The time in milliseconds the request took to process in the backend |
wid |
String | 407fe8f |
the worker cache ID |
revision |
Integer | f67190d |
The current commit ID |
Project information is identical to the statistics
section explained in the Project information
section with the value info
added, this is explained below
Key | Value | Example | Description |
---|---|---|---|
username |
String | griffpatch |
Username of the project author |
title |
String | Paper Minecraft v11.5 (Minecraft 2D) |
Title of the project |
scratch_id |
Integer | 10128407 |
The Scratch ID of the project |
sys_id |
Integer | 15838 |
The ScratchDB ID of the project |
Usage: /v2/project/info/user/[username]
This endpoint is used to get information about all projects by a user
The response is identical to one of the Project Positioning Rankings
endpoint.
Note: if the user has a project under 1000 views, it will not include the ranks
object
This endpoint returns information about a user on the forums.
Usage /v2/forum/user/info/[username]
Example Response:
{
"firstPost": ...
"lastPost": ...
"counts": {
"Suggestions": {
"count": 2415,
"rank": 7
},
"Bugs and Glitches": {
"count": 1773,
"rank": 1
},
"Questions about Scratch": {
"count": 2603,
"rank": 4
},
...
"total": {
"count": 15591,
"rank": 2
}
},
"wid": "1982185",
"revision": "1c72b6f",
"query_time": 2439
}
Key | Value | Example | Description |
---|---|---|---|
firstPost |
Object | The user's first post, uses post format under "Forum Post Information" | |
lastPost |
Object | The user's most recent post, uses format under "Forum Post Information" | |
counts |
Object | The user's post totals, similar format to "Category ranking" | |
query_time |
Integer | 57 |
The time in milliseconds the request took to process in the backend |
wid |
String | 6ae1703 |
the worker cache ID |
revision |
String | 1c72b6f |
The current commit |
This endpoint returns information about a single forum post
Usage: /v2/forum/post/[id]
Example Response:
{
"id": 28,
"username": "ricarose",
"editor": null,
"deleted": 0,
"time": {
"posted": "2012-08-31T02:54:06.000Z",
"first_checked": "2019-11-17T22:26:19.000Z",
"html_last_checked": "2019-11-17T22:26:19.000Z",
"bbcode_last_checked": "2019-11-17T22:26:19.000Z",
"edited": null
},
"content": {
"html": "As you begin to use the prototype, we would love to know your initial thoughts and experiences. Sometimes those first moments can tell a lot about what is easy or confusing. Here are some questions to help you think about your initial experiences:<br><br>* What were your initial series of actions on the prototype?<br><br>* What did you find confusing or frustrating? <br><br>* What features did you like?<br><br>P.S. Don't be afraid to be really honest – our feelings will not be hurt!",
"bb": "As you begin to use the prototype, we would love to know your initial thoughts and experiences. Sometimes those first moments can tell a lot about what is easy or confusing. Here are some questions to help you think about your initial experiences:\r\n\r\n* What were your initial series of actions on the prototype?\r\n\r\n* What did you find confusing or frustrating? \r\n\r\n* What features did you like?\r\n\r\nP.S. Don't be afraid to be really honest -- our feelings will not be hurt!"
},
"topic": ...
"revision": "4e4b9f8",
"query_time": 13
}
The data returned is an object with the following content:
Key | Value | Example | Description |
---|---|---|---|
id |
Integer | 28 |
Forum post ID |
username |
String | ricarose |
Forum post author |
editor |
String | Username of the last person to edit a post | |
deleted |
Boolean | 0 |
Whether the post is deleted (1) or not (0) |
time |
Object | Object filled with different times about the post | |
time.posted |
Timestamp | 2012-08-31T02:54:06.000Z |
Time when the post was posted |
time.first_checked |
Timestamp | 2019-11-17T22:26:19.000Z |
Time when the post was first seen by ScratchIndexer |
time.html_last_checked |
Timestamp | 2019-11-17T22:26:19.000Z |
Time when ScratchIndexer last checked the post's HTML* |
time.bbcode_last_checked |
Timestamp | 2019-11-17T22:26:19.000Z |
Time when ScratchIndexer last checked the posts' BBCode |
time.edited |
Timestamp | Time when the post was last edited, if it was | |
topic |
Object | Topic object explained under "Forum Posts in Topic" | |
content |
Object | Post content, explained in next values | |
content.html |
String | Post HTML from the forums | |
content.bb |
String | Post BBCode from the source | |
revision |
String | 86cd183 |
The current commit ID |
query_time |
Integer | 1 |
The time in milliseconds the request took to process in the backend |
If a post is not defined, it will have a value called scratch_error
which will have the error code that scratch returned (ex, 404
, 403
)
Most forum endpoints will follow this format, wid
may not be in all of them
Example response:
{
"posts": [
{
"id": 215339,
"username": "Harakou",
...
}
...]
],
"revision": "1c72b6f",
"query_time": 2
}
The data returned is an object with the following content:
Key | Value | Example | Description |
---|---|---|---|
posts |
Object | A list of up to 100 posts, posts in format explained above | |
revision |
String | 1c72b6f |
The current commit |
query_time |
Integer | 3 |
The time in milliseconds the request took to process in the backend |
wid |
String | 427ee8f |
the worker cache ID (Only in endpoints that use the worker cache) |
This endpoint gets a list of posts by a user, newest first
Usage: /v2/forum/user/posts/[username]
If the user doesn't exist and/or has no posts, posts
will contain an empty array
For posts, this uses the same format explained above
This endpoint gets a list of posts in a topic, newest first
Usage: /v2/forum/topic/[id]
Example Response:
{
"id": 13,
"name": "Interesting, we have RSS feed for specific topics!",
"title": "Interesting, we have RSS feed for specific topics!",
"category": "Suggestions",
"closed": 0,
"deleted": 0,
"time": {
"first_checked": "2019-11-17T22:26:21.000Z",
"last_checked": "2019-11-17T22:09:41.000Z"
},
"posts": [...],
"revision": "4e4b9f8",
"query_time": 2
}
If the topic does not exist, error
will be notfound
Key | Value | Example | Description |
---|---|---|---|
id |
Integer | 13 |
Topic ID |
title |
String | Interesting, we have RSS feed for specific topics! |
Topic title |
category |
String | Suggestions |
Category the topic is in |
closed |
Boolean | 0 |
If the topic is closed (1) or not (0) |
deleted |
Boolean | 0 |
If the topic is deleted (1) or not (0) |
time |
Object | Topic information | |
time.first_checked |
Timestamp | 2019-11-17T22:26:21.000Z |
Time when ScratchIndexer first checked the topic |
time.last_checked |
Timestamp | 2019-11-17T22:26:21.000Z |
Time when ScratchIndexer last checked the topic |
time.cached |
Timestamp | Timestamp if this was cached. Average time is 15 minutes | |
posts |
Object | Object of posts. Uses format above, topic is null |
|
revision |
String | 4e4b9f8 |
The current commit |
query_time |
Integer | 2 |
The time in milliseconds the request took to process in the backend |
For posts, this uses the same format explained above
This endpoint gets a list of posts given a query
Usage: /v2/forum/search
This endpoint accepts a set of different arguments.
q
is for the query you want to searchpage
is the page in the search to go by. Remember, arrays start at 0, so pages do as well.o
can be set to newest
or oldest
to sort by, you guessed it, newest or oldest based on your queryIn search you are able to include a few requirements in the returned data by using +
, -
, ~
, and quotes.
Generally to add a requirement you do +requirement:term
or +requirement:"multiple word term"
+
means it is required to be true-
means it is required to be false~
means it should be true, but is not requiredGeneral words searched are added to a ~
list, but are not necessairly required.
If you want to require a quoted sentence, you can do "this needs to be required"
instead of having to do +content:"this needs to be required"
The possible requirements are username, "category, topic, title, id, content
.
Note: variables do not have to be complete, if you did +title:Advanced
, all topics with the word "Advanced" in them would be included
Important note: the format of a query may change since this is a newly changing endpoint. Once I get some feedback, I may tweak the format a bit. Don't worry, the JSON response should be relatively the same
Another important note: encodeURIComponent
(at least in JS) may be required in order to get +
and other symbols to be searched. for example, "/v2/forum/search?q=" + encodeURIComponent("+username:za-chary")
will be needed, since + normally can stand for a space
For the time being, you cannot select by category ID, this will be coming soon.
Example Response:
{
"posts": [],
"query": {
"original": "+username:Paddle2See +category:Suggestions",
"query": {
"must": [
{
"username": "Paddle2See"
},
{
"category": "Suggestions"
}
],
"should": [],
"must_not": []
}
},
"hits": 3883,
"revision": "f02476c",
"query_time": 320
}
Key | Value | Example | Description |
---|---|---|---|
posts |
Object | Object of posts, uses the format above | |
query |
Object | Object of your parsed query | |
hits |
Integer | 0 | Number of posts that match your query |
This endpoint gets a list of the top posters in a category
Usage: /v2/forum/category/rank/[category]/[page]
Instead of a category
, you can use total
for forum-wide counts.
Exmaple Response:
{
"users": [
{
"username": "deck26",
"count": 27556,
"rank": 1
},
{
"username": "CatsUnited",
"count": 15591,
"rank": 2
},
{
"username": "Sigton",
"count": 13941,
"rank": 3
},
{
"username": "Paddle2See",
"count": 13832,
"rank": 4
},
...
],
"query_time": 57,
"wid": "6ae1703",
"revision": "1c72b6f"
}
This will return an object with the following format
Key | Value | Example | Description |
---|---|---|---|
users |
Object | A list of users, format explained below | |
users.username |
String | CatsUnited |
Username of the user |
users.count |
Integer | 15591 |
Number of posts matching the query |
users.rank |
Integer | 2 |
User's rank |
query_time |
Integer | 57 |
The time in milliseconds the request took to process in the backend |
wid |
String | 6ae1703 |
the worker cache ID |
revision |
String | 1c72b6f |
The current commit |
If the topic does not exist, posts
will contain an empty array
ScratchDB v2 development is more or less finished. Some bug fixes may come to this code, but due to the mess of the backend some things may not be fixed until v3
ScratchDB was written by DatOneLefty and is not affiliated, endorsed, nor maintained by the Lifelong Kindergarten Group or the Scratch Team.
All content on this site falls under the Creative Commons Attribution-ShareAlike 2.0 license
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Revision: d58188e