API Surface
The package exposes browser APIs under the WebAPI namespace. In normal application code,
add the package to rescript.json:
{ "dependencies": ["@rescript/webapi"]}Use WebAPI.DOM.window for the browser window. Interface-specific methods live on
public modules such as WebAPI.Window, WebAPI.Location, WebAPI.Document,
WebAPI.Element, WebAPI.Request, and WebAPI.Response.
let location = WebAPI.DOM.window->WebAPI.Window.locationlet href = location.href
location->WebAPI.Location.reloadPublic module shape
Section titled “Public module shape”The public API is flat under WebAPI. Use owner modules directly rather than generated
helper modules.
let req: WebAPI.Request.t = WebAPI.Request.fromURL("https://example.com")let headers = WebAPI.Headers.make()let document = WebAPI.DOM.window->WebAPI.Window.documentlet element = document->WebAPI.Document.createElement("button")Generated implementation modules such as DomTypes, FetchTypes, EventTypes, and
UiEventsTypes are internal. If you need to name a public type, use the public interface
module’s t type when it has one, or use a dedicated public type module. Otherwise, let
the value type be inferred from constructors and accessors.
Consumer feature bundles
Section titled “Consumer feature bundles”Feature names select related bindings and their transitive dependencies. They do not add
another namespace segment. For example, selecting WebAPI.Fetch enables flat modules such
as WebAPI.Fetch, WebAPI.Request, WebAPI.Response, and WebAPI.Headers.
{ "dependencies": [ { "name": "@rescript/webapi", "features": ["WebAPI.Fetch", "WebAPI.HTML"] } ]}The supported feature bundles are:
WebAPI.DOM WebAPI.Event WebAPI.DOMPlatformWebAPI.DOMNodes WebAPI.File WebAPI.HTMLWebAPI.Window WebAPI.CSSOM WebAPI.CSSFontLoadingWebAPI.Geometry WebAPI.SVG WebAPI.AnimationWebAPI.Device WebAPI.Navigator WebAPI.CanvasWebAPI.URL WebAPI.Fetch WebAPI.UIEventsWebAPI.Observers WebAPI.Media WebAPI.WebAudioWebAPI.Storage WebAPI.Messaging WebAPI.WorkersWebAPI.Crypto WebAPI.Performance WebAPI.ViewTransitionsThe package owns each bundle as one internal source folder. Those internal folder feature names are an implementation detail; consumers should use only the qualified names above.
Use WebAPI.Fetch.fetch for string URLs and WebAPI.Fetch.fetchWithRequest
when you already have a WebAPI.Request.t.
let response = await WebAPI.Fetch.fetch("https://example.com/api/users")
if response.ok { let body = await response->WebAPI.Response.json Console.log(body)} else { Console.log("Request failed") Console.log(response.status)}For JSON-style POST requests, construct headers with HeadersInit and the body with
BodyInit.
let response = await WebAPI.Fetch.fetch( "https://example.com/api/users", ~init={ method: "POST", headers: WebAPI.HeadersInit.fromDict( dict{ "Accept": "application/json", "Content-Type": "application/json", }, ), body: WebAPI.BodyInit.fromString(`{"name":"ReScript"}`), },)
let text = await response->WebAPI.Response.textBodyInit has constructors for the common JavaScript body shapes.
let params = WebAPI.URLSearchParams.fromString("q=rescript")let formData = WebAPI.FormData.make()let blob = WebAPI.Blob.make(~blobParts=[])
let stringBody = WebAPI.BodyInit.fromString("plain text")let paramsBody = WebAPI.BodyInit.fromURLSearchParams(params)let formDataBody = WebAPI.BodyInit.fromFormData(formData)let blobBody = WebAPI.BodyInit.fromBlob(blob)Headers
Section titled “Headers”Use WebAPI.HeadersInit when a fetch, request, or response initializer expects the
JavaScript HeadersInit shape. Use WebAPI.Headers when you want a mutable Headers
object with methods.
let initHeaders = WebAPI.HeadersInit.fromDict( dict{ "Accept": "application/json", "X-Client": "web", },)
let response = await WebAPI.Fetch.fetch( "https://example.com/api/users", ~init={headers: initHeaders},)Build and edit a Headers object directly when you need to append, set, inspect, or pass
headers around.
let headers = WebAPI.Headers.fromDict(dict{"Accept": "application/json"})
headers->WebAPI.Headers.set(~name="X-Request-ID", ~value="abc-123")headers->WebAPI.Headers.append(~name="X-Trace", ~value="enabled")
switch headers->WebAPI.Headers.get("Accept") {| Null.Value(value) => Console.log(value)| Null => Console.log("missing")}
let hasTrace = headers->WebAPI.Headers.has("X-Trace")Headers can also be created from key-value arrays or copied from another Headers object.
let fromPairs = WebAPI.Headers.fromKeyValueArray([ ("Accept", "application/json"), ("X-Client", "web"),])
let clonedHeaders = WebAPI.Headers.fromHeaders(fromPairs)let initFromHeaders = WebAPI.HeadersInit.fromHeaders(clonedHeaders)Response headers are normal Headers values.
let contentType = response.headers->WebAPI.Headers.get("Content-Type")
switch contentType {| Null.Value(value) => Console.log(value)| Null => Console.log("unknown content type")}Requests
Section titled “Requests”Create requests from URLs, then pass them to fetch or clone/read them with request methods.
let req = WebAPI.Request.fromURL( "https://example.com/form", ~init={ method: "POST", headers: WebAPI.HeadersInit.fromDict( dict{"Content-Type": "application/x-www-form-urlencoded"}, ), body: WebAPI.BodyInit.fromString("name=ReScript"), },)
let response = await WebAPI.Fetch.fetchWithRequest(req)let cloned: WebAPI.Request.t = req->WebAPI.Request.clonelet bodyText = await cloned->WebAPI.Request.textUse fromRequest to copy an existing request and override initializer fields.
let authenticatedHeaders = WebAPI.HeadersInit.fromDict( dict{ "Accept": "application/json", "Authorization": "Bearer token", },)
let authenticatedReq = WebAPI.Request.fromRequest( req, ~init={headers: authenticatedHeaders},)
let authenticatedResponse = await WebAPI.Fetch.fetchWithRequest(authenticatedReq)Request body readers mirror the browser API and return promises.
let requestText = await req->WebAPI.Request.textlet requestJson = await req->WebAPI.Request.jsonlet requestBlob = await req->WebAPI.Request.blobResponses
Section titled “Responses”Construct responses with the body constructor that matches the body value.
let created = WebAPI.Response.fromString( "created", ~init={ status: 201, statusText: "Created", headers: WebAPI.HeadersInit.fromDict(dict{"Content-Type": "text/plain"}), },)
let empty = WebAPI.Response.fromNull(~init={status: 204})Responses expose record fields for status metadata and methods for cloning or reading the body.
if created.ok { let text = await created->WebAPI.Response.text Console.log(text)} else { Console.log(created.statusText)}
let copy = created->WebAPI.Response.clonelet copyText = await copy->WebAPI.Response.textUse the static helpers for browser response factories.
let failed = WebAPI.Response.error()let redirect = WebAPI.Response.redirect(~url="/login", ~status=302)DOM values are operated on through public interface modules.
let document = WebAPI.DOM.window->WebAPI.Window.document
let maybeButton = document->WebAPI.Document.querySelector("button")->Null.toOption
switch maybeButton {| Some(button) => switch button->WebAPI.Element.getAttribute("data-user-id") { | Null.Value(id) => Console.log(id) | Null => Console.log("anonymous") }| None => Console.log("button not found")}Use conversion helpers when moving between related DOM interface types.
let element = document->WebAPI.Document.createElement("div")let node = element->WebAPI.Element.asNodeClassifying DOM values
Section titled “Classifying DOM values”Event libraries and browser APIs sometimes return a type that is broader than the value present at runtime. A React form event target, for example, does not tell ReScript whether the target is an input, select, or another element. Calling an input-specific API then requires narrowing that value.
Use classify instead of repeating an instanceof binding and an unchecked Obj.magic cast. The
classifier performs the runtime check and returns the correctly typed value as an option.
let readInputValue = target => switch target->WebAPI.HTMLInputElement.classify { | Some(input) => Some(input.value) | None => None }The classifier parameter is polymorphic, so a library-owned target can be passed directly without an
identity cast to a WebAPI type first. Element.classify, Document.classify,
HTMLElement.classify, HTMLInputElement.classify, HTMLImageElement.classify, and
HTMLCanvasElement.classify follow the same contract. Their matching isInstanceOf functions are
available when only a boolean check is needed.
Classification uses the corresponding constructor from globalThis. It returns None rather than
raising when that constructor is unavailable in a server or worker environment. Like JavaScript
instanceof, it only recognizes values created in the current realm; values from another window or
iframe may not match. Enable the WebAPI.HTML feature for HTML-specific classifiers and
WebAPI.Canvas for HTMLCanvasElement.classify.
Visual Viewport
Section titled “Visual Viewport”Window.visualViewport returns a nullable WebAPI.VisualViewport.t.
let maybeViewport = WebAPI.DOM.window->WebAPI.Window.visualViewport->Null.toOption
switch maybeViewport {| Some(viewport) => Console.log(Float.toString(viewport.width)) Console.log(Float.toString(viewport.scale))| None => Console.log("visual viewport unavailable")}URL helpers expose constructors and static functions on the same public module.
let url = WebAPI.URL.make(~url="/docs", ~base="https://rescript-lang.org")let canParse = WebAPI.URL.canParse(~url="/docs", ~base="https://rescript-lang.org")let json = url->WebAPI.URL.toJSONURLSearchParams values can be used directly as fetch request bodies through BodyInit.
let params = WebAPI.URLSearchParams.fromString("search=rescript")let response = await WebAPI.Fetch.fetch( "https://example.com/search", ~init={ method: "POST", body: WebAPI.BodyInit.fromURLSearchParams(params), },)Canvas
Section titled “Canvas”Canvas constructors use make and semantic from* names.
let path = WebAPI.Path2D.make()
path->WebAPI.Path2D.moveTo(~x=0., ~y=0.)path->WebAPI.Path2D.lineTo(~x=100., ~y=100.)
let copiedPath = WebAPI.Path2D.fromPath2D(path)let svgPath = WebAPI.Path2D.fromString("M0 0 L10 10")Streams
Section titled “Streams”Generic Web API types stay typed through their public owner modules.
let stream: WebAPI.ReadableStream.t<string> = WebAPI.ReadableStream.make()let reader = stream->WebAPI.ReadableStream.getReader