# Browser handoff API reference

> Canonical HTML: https://screenrig.ai/docs/api/browser-handoff
> Source SHA-256: e0c997a2ab813502f0d99a41d2ed1d3d6b26dbaf1a3d7e514c1cce0278ff8422

Homepage browser handoff. This group has 6 operations, each with its authentication, parameters, request body fields, request template and responses. The [API overview](https://screenrig.ai/docs/api.md) covers services, authentication, requests and retries, problem codes and versioning.

Replace uppercase placeholders. Save a schema-valid JSON body in request.json when required. Cookie examples use a local cookie jar from an authenticated session.

## Homepage browser handoff

### POST /api/project/browser-links/claim

**Claim Browser Link**

Claims one browser-link code for the authenticated project and atomically creates exactly one first pairing_pending screen plus its existing browser provisioning grant. Enrollment remains project-only. The response is safe metadata only and never contains a provisioning token, fragment URL, cookie, or proof.


Operation: claimBrowserLink.

- Authentication: projectBearer
- Request body: BrowserLinkClaimRequest

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| ScreenRig-Project | header | optional | Deprecated for one release. Must be consistent with the JWT projects grants; adds Deprecation and Warning headers. No token exchange. |
| Idempotency-Key | header | required |  |

#### Request body fields

| Field | Required? | Type | Description |
| --- | --- | --- | --- |
| code | required | string | pattern: "^[23456789ABCDEFGHJKMNPQRSTUVWXYZ]{3}-?[23456789ABCDEFGHJKMNPQRSTUVWXYZ]{3}$" |

#### Request template

~~~sh
curl --request POST --header 'Authorization: Bearer [SCREENRIG_TOKEN]' --header 'Idempotency-Key: REQUEST_ID' --header 'Content-Type: application/json' --data '@request.json' 'https://api.screenrig.ai/api/project/browser-links/claim'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 201 | Exact replay-safe fragment-free browser-link claim. | BrowserLinkClaim (application/json); headers: Cache-Control, RateLimit-Policy, RateLimit |
| 400 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 403 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 404 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 409 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 410 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 429 | Stable rate_limited problem. Retry only after the authoritative Retry-After interval. Fixed-window denials also include the applicable RateLimit-Policy and RateLimit members; concurrency and byte-budget denials omit those optional disclosures. | Problem (application/problem+json); headers: Retry-After, RateLimit-Policy, RateLimit |
| 500 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |

### GET /screen/browser-links

**Get Browser Link Status**

Read-only polling fallback authenticated only by the owning apex browser-link cookie. It returns safe status metadata and the fixed continuation path, never a provisioning URL or token.


Operation: getBrowserLinkStatus.

- Authentication: browserLinkCookie
- Request body: none

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/screen/browser-links'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Claimed safe status. | BrowserLinkStatus (application/json); headers: Cache-Control, Referrer-Policy |
| 202 | Browser link exists but is not claimed yet. | BrowserLinkStatus (application/json); headers: Cache-Control, Referrer-Policy |
| 401 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| 410 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### POST /screen/browser-links

**Start Browser Link**

Strict same-origin no-JavaScript-compatible POST that creates or reuses a 24-hour unclaimed browser-link session. Claiming within that window creates a fresh, independent ten-minute protected provisioning-delivery window; cookie Player pairing lasts 24 hours.

Native pairing is a separate seventy-two-hour unclaimed locator; claimed native delivery remains durable until signed completion or explicit on-player reset. It sets exactly the apex host-only Secure HttpOnly SameSite=Strict Path=/ __Host-screenrig-browser-link cookie with no Domain.

JSON clients receive 201; Accept text/html receives a bodyless 303 to /setup. No insecure localhost fallback exists; development requires the configured HTTPS loopback origin.


Operation: startBrowserLink.

- Authentication: none
- Request body: none

#### Request template

~~~sh
curl --request POST 'https://screenrig.ai/screen/browser-links'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 201 | Safe browser-link code/status metadata. | BrowserLinkSession (application/json); headers: Cache-Control, Referrer-Policy, Set-Cookie, RateLimit-Policy, RateLimit |
| 303 | No-JavaScript form continuation to the read-only setup page. | no body; headers: Location, Cache-Control, Referrer-Policy, Set-Cookie |
| 403 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| 409 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| 429 | Stable rate_limited problem on a Player-facing runtime or content route, in the runtime document shape (RuntimeProblem). Retry only after the authoritative Retry-After interval. Fixed-window denials also include the applicable RateLimit-Policy and RateLimit members; concurrency and byte-budget denials omit those optional disclosures. | RuntimeProblem (application/problem+json); headers: Retry-After, RateLimit-Policy, RateLimit |
| 500 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### GET /stream/browser-links/events

**Stream Browser Link Events**

Owning-cookie-only replayable SSE with Last-Event-ID. Event data contains safe status fields only. It never contains a provisioning URL/token and does not use the project event stream.


Operation: streamBrowserLinkEvents.

- Authentication: browserLinkCookie
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| Last-Event-ID | header | optional | Durable cursor used when after is absent. |

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/stream/browser-links/events'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Browser-link issued/claimed status SSE. | string (text/event-stream); headers: Cache-Control, Referrer-Policy, X-Accel-Buffering |
| 400 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| 401 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| 410 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### GET /screen/browser-links/continue

**Continue Browser Link**

Navigation-only owning-cookie-authenticated GET. After claim it returns a bodyless 303 whose sensitive Location is the exact Player /s/<public_id>#provision=<token> URL. The Location is never exposed through CORS, JSON, SSE, polling, logs, traces, metrics, analytics, events, or errors and is idempotent only during the short delivery repair window.


Operation: continueBrowserLink.

- Authentication: browserLinkCookie
- Request body: none

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/screen/browser-links/continue'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 303 | Bodyless redirect to the Player provisioning fragment. | no body; headers: Location, Cache-Control, Referrer-Policy |
| 401 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| 409 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| 410 | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |
| default | Stable RFC 9457 problem response on a Player-facing runtime, content, or probe route, in the runtime document shape (RuntimeProblem). A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | RuntimeProblem (application/problem+json) |

### GET /setup

**Get Browser Link Setup Page**

Read-only setup instructions. Without code, the owning browser-link cookie supplies status. With code, returns public-only instructions, using generic 404 for invalid or expired codes. Accept text/markdown or format=markdown selects Markdown for the public code form. No provisioning URL or token is returned.


Operation: getBrowserLinkSetupPage.

- Authentication: browserLinkCookie OR none
- Request body: none

#### Parameters

| Name | Send in | Required? | Description |
| --- | --- | --- | --- |
| code | query | optional | Public setup code for side-effect-free setup instructions; no cookie required. |
| format | query | optional |  |

#### Request template

~~~sh
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/setup'
~~~

#### Responses

| Status | Meaning | Body and headers |
| --- | --- | --- |
| 200 | Safe noindex setup HTML. | string (text/html); headers: Cache-Control, Referrer-Policy, X-Robots-Tag |
| 401 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| 410 | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |
| default | Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value. | Problem (application/problem+json) |


## Sitemap

See the [public documentation sitemap](https://screenrig.ai/sitemap.md).
