Reference

The package exports ScratchSession, the resource classes (Users, Projects, Studios, Search), the cloud classes (Cloud, CloudRequests, CloudEvents, CloudStorage), the database adapters (MemoryDatabase, JsonDatabase, SqlDatabase), the Encoding helpers (encode, decode) and ScratchAPIError. In normal use you only construct a ScratchSession — everything else is reached through it.

import { ScratchSession, ScratchAPIError } from 's-api4js';

ScratchSession

The entry point. Owns the cookie jar, holds auth state, and exposes the resource groups.

Construction

new ScratchSession(options?)
ScratchSession.login(username, password, options?) // → Promise<ScratchSession>

options:

OptionDefaultPurpose
jarnew CookieJarThe tough-cookie store.
fetchglobal fetchCustom fetch implementation.
userAgentpackage UAUser-Agent header for every request.

Properties

PropertyTypeNotes
loggedInbooleantrue once authenticated (getter).
usernamestring | nullSet after login.
userIdnumber | nullSet after login.
xTokenstring | nullX-Token for authenticated calls.
csrfTokenstring | nullCSRF token paired with the session cookie.
jarCookieJarThe shared cookie jar (getter).
users / projects / studios / searchresourceThe API groups.
apiHost / projectsHost / assetsHost / siteHoststringBase URLs.

Methods

MethodDescription
login(username, password)Authenticate this session in place. → this
refreshSession()Re-read auth state from /session/.
logout()Clear the server session and local auth state.
health()GET /health.
news()GET /news.
featured()GET /proxy/featured.
Lower-level helpers

apiGet(path, params?), authedJson(url, options?, extraHeaders?), authedFetch(url, options?, extraHeaders?), authHeaders() and requireAuth() are used internally by the resource classes and are available if you need to call an endpoint that doesn't have a dedicated method yet.

session.users

MethodEndpoint
get(username)GET /users/<username>
followers(username, page?)GET /users/<username>/followers
following(username, page?)GET /users/<username>/following
favorites(username, page?)GET /users/<username>/favorites
projects(username, page?)GET /users/<username>/projects

page is { limit?, offset? } (Scratch caps limit at 40).

session.projects

Reads (no login required for shared content):

MethodEndpoint
get(id)GET /projects/<id>
remixes(id, page?)GET /projects/<id>/remixes
comments(id, page?)GET /users/<author>/projects/<id>/comments
token(id)GET /projects/<id>project_token
getJson(id, token?)GET projects.scratch.mit.edu/<id>?token=…
downloadAsset(md5ext)GET assets.scratch.mit.edu/<md5ext>
download(id)getJson + every referenced asset → { json, assets }

Writes (require login + ownership):

MethodEndpoint
setJson(id, json)PUT projects.scratch.mit.edu/<id>
uploadAsset(md5ext, bytes)POST assets.scratch.mit.edu/<md5ext>
save(id, project)upload all assets, then setJson
setMetadata(id, { title?, instructions?, description? })PUT /projects/<id>
setTitle(id, title)shortcut for setMetadata
setInstructions(id, instructions)shortcut for setMetadata
setDescription(id, description)shortcut for setMetadata
share(id)PUT /proxy/projects/<id>/share
unshare(id)PUT /proxy/projects/<id>/unshare

save() accepts a scratch4js Project or any { json, assets }, where assets is a Map/object of md5ext → Uint8Array or an array of [md5ext, bytes] pairs. See Editing projects.

session.studios

MethodEndpoint
get(id)GET /studios/<id>
projects(id, page?)GET /studios/<id>/projects
curators(id, page?)GET /studios/<id>/curators
managers(id, page?)GET /studios/<id>/managers
comments(id, page?)GET /studios/<id>/comments

session.search

Each takes { mode?, language?, limit?, offset? }, where mode is 'popular' (default) or 'trending'.

MethodEndpoint
projects(q, opts?)GET /search/projects
studios(q, opts?)GET /search/studios
exploreProjects(q?, opts?)GET /explore/projects (q defaults to *)
exploreStudios(q?, opts?)GET /explore/studios

session.cloud(projectId, options?)

Returns a Cloud. For Scratch (the default host) this requires login and attaches the session cookie; pass a custom host and it's treated as unauthenticated (no login, no cookie). options overrides the defaults:

OptionDefaultPurpose
hostwss://clouddata.scratch.mit.eduCloud WebSocket URL (custom/TurboWarp).
allowNonNumericfalsePermit non-numeric values.
lengthLimit256Max value length.
rateLimit0.1Minimum seconds between sets.
userAgentsession UAUser-Agent header (e.g. for TurboWarp).
cookiesession cookie (Scratch only)Cookie header.
WebSocketws, then globalThis.WebSocketWebSocket implementation.

Other ways to construct one, no session needed:

Cloud.turbowarp(projectId, { purpose?, contact?, userAgent?, ... }) // TurboWarp preset
new Cloud({ projectId, host, ... }) // any server

Constants: Cloud.SCRATCH_HOST, Cloud.TURBOWARP_HOST. The Cloud.isScratch getter reports whether a connection targets Scratch.

Cloud

MethodDescription
connect() / disconnect() / reconnect()Manage the WebSocket (the first setVar connects too).
setVar(name, value)Set one variable (serialized + rate-limited).
setVars({ … })Set several, in order.
getVar(name) / getAllVars()Latest value(s) seen since connecting.
logs({ variable?, limit?, offset? })GET clouddata.scratch.mit.edu/logs (no login needed).
on(event, fn) / off(event, fn)Events: set, connect, disconnect, error.
requests(options?)Build a CloudRequests on this cloud.
events(options?)Build a CloudEvents log poller.
storage(options?)Build a CloudStorage key-value store.

CloudRequests

Built with cloud.requests({ requestVar?, usedCloudVars? }).

MethodDescription
request(name, handler)Register a handler (args, ctx) => string | number | string[].
removeRequest(name)Remove a handler.
start() / stop()Begin / stop handling requests.
on(event, fn)Events: request, unknownRequest, error.

The handler ctx is { name, args, requestId, requester }.

CloudEvents

Built with cloud.events({ source?, interval?, limit? }). source is 'logs' (Scratch — polls the public log, reports the user and create/delete, works without login) or 'websocket' (TurboWarp/custom — listens on the socket; only set fires). It defaults to logs on Scratch and websocket elsewhere.

MethodDescription
on(event, fn)Events: ready, set, create, delete, error.
start() / stop()Begin / stop emitting events.

Activity events receive { user, verb, name, value, timestamp } (user and timestamp are null in websocket mode).

CloudStorage

Built with cloud.storage(options?) — a cloud-backed key-value store (scratchattach's Cloud Storage protocol). Serves get, set, keys, database_names and ping requests over the cloud.

MethodDescription
addDatabase(db)Register a database (addressed by its name).
getDatabase(name)Look up a registered database.
start() / stop()Begin / stop serving storage requests.
on(event, fn)Events: request, unknownRequest, error.

Databases implement { name, get(key), set(key, value), keys() }. Bundled:

ClassBacking store
MemoryDatabaseIn-memory (not persisted).
JsonDatabaseA JSON file ({ path }).
SqlDatabaseSQLite / MySQL / MariaDB / PostgreSQL — { dialect, query, table? }.

SqlDatabase needs no bundled driver: pass a query(sql, params) wrapping your client (better-sqlite3, mysql2, pg, …) that resolves to an array of row objects. See Cloud variables & requests.

ScratchAPIError

Thrown on any non-2xx response (or a failed request). Extends Error.

PropertyTypeDescription
namestring'ScratchAPIError'.
messagestringHuman-readable summary.
statusnumber | undefinedHTTP status, if a response came back.
urlstring | undefinedThe request URL.
methodstring | undefinedThe request method.
bodyunknownParsed JSON (or raw text) response body.
import { ScratchAPIError } from 's-api4js';

try {
  await session.projects.save(123, project);
} catch (err) {
  if (err instanceof ScratchAPIError) {
    console.error(err.status, err.url, err.body);
  }
}