List Screen Records
Use this method to retrieve the stored recording-segment metadata for one Device Park session. Recording must be enabled when the session is started.
screenRecords(...) and Session.videoRecordUrl serve different purposes:
SDK value | Returns | Use it for |
|---|---|---|
client.sessions().screenRecords(...) | PageDto<ScreenRecord> JSON | Listing and filtering the stored recording segments |
Session.videoRecordUrl | RFC 8216-compatible HLS media-playlist URL | Playing the complete session recording in an HLS player |
Do not pass a ScreenRecord.downloadUrl to an HLS player. It addresses one stored recording segment; videoRecordUrl addresses the playlist that orders the segments into the complete recording.
Before You Begin
- Start the session with videoRecording(true).
- Store the returned sessionId.
- Stop the session and allow recording processing to complete.
SDK Method
Java | Node.js | Returns |
|---|---|---|
client.sessions().screenRecords(sessionId, request) | await client.sessions().screenRecords(sessionId, request?) | PageDto<ScreenRecord> |
Request Fields
Input | Type | Required | Default | Description |
|---|---|---|---|---|
sessionId | string | Yes | - | Device Park session identifier |
.page(value) | integer | No | 0 | Zero-based page index |
.size(value) | integer | No | 20 | Maximum records requested |
.sortBy(value) | string | No | ID | Server-side sort field |
.direction(value) | SortDirection | No | DESC | ASC or DESC |
.addFilter(...) | filter rule | No | None | Adds a recording filter |
Available Screen Record Filters
Constant | Expected value | Supported operations | Purpose |
|---|---|---|---|
ScreenRecordFilter.CREATED_AT | Timestamp string | EQUAL, NOT_EQUAL, GREATER_THAN, LESS_THAN | Filter by recording creation time |
The Java and Node.js SDKs transmit this filter to Device Park.
Request Mapping
sessionId identifies the parent session. The list request has no body. Both SDKs map pagination, sorting and filters to query data. OAuth authorization is managed by the SDK client.
Examples
ScreenRecordFilterRequest filterRequest = ScreenRecordFilterRequest.of(
ScreenRecordFilter.CREATED_AT,
"2026-07-28T00:00:00Z",
SearchOperation.GREATER_THAN
);
PageDto<ScreenRecord> records = client.sessions().screenRecords(
"session-123",
ScreenRecordPaginationRequest.builder()
.filters(Collections.singletonList(filterRequest))
.page(0)
.size(20)
.build()
);Response Model
Field | Type | Nullable | Meaning |
|---|---|---|---|
fileKey | string | Yes | Stable identifier for one stored recording segment |
filePath | string | Yes | Server-side path of the segment, commonly an MPEG-TS (.ts) file |
downloadUrl | string | Yes | Potentially time-limited URL for this individual segment; not the HLS playlist |
createdAt | ISO-8601 string | Yes | Creation timestamp |
updatedAt | ISO-8601 string | Yes | Last processing update |
duration | number | Yes | Recording duration reported by Device Park |
{
"size": 20,
"page": 0,
"totalPages": 1,
"totalElements": 1,
"data": [
{
"fileKey": "recording-segment-001",
"filePath": "screen-records/session-123/recording-001.ts",
"downloadUrl": "https://storage.example/temporary-recording-segment-url",
"createdAt": "2026-07-28T10:00:00Z",
"updatedAt": "2026-07-28T10:15:00Z",
"duration": 9.5
}
]
}An empty successful page can mean recording processing is not complete. Retry with a bounded interval. Do not treat downloadUrl as permanent.
Play the Complete Recording with HLS
When videoRecording is true, Device Park sets Session.videoRecordUrl after the session is closed and its recording is ready. Until then, videoRecordUrl can be null. Retrieve the session again with client.sessions().list(...) rather than relying on the response returned when the session was started.
The URL returns a UTF-8 HLS media playlist. It is not a single MP4 file. The playlist contains ordered media-segment URLs and durations; an HLS player loads the playlist and then requests those segments. The response is identified by the application/vnd.apple.mpegurl content type, so the URL does not have to end in .m3u8. This follows RFC 8216.
The SDK discovers the stream URL; it does not decode or play video. Your application must give videoRecordUrl to an HLS-capable player or proxy the playlist and its segments to that player. Authorization applies to both the initial playlist request and the subsequent segment requests.
Find the HLS URL with the SDK
import io.testinium.devicepark.model.common.PageDto;
import io.testinium.devicepark.model.common.SearchOperation;
import io.testinium.devicepark.model.sessions.DeviceSessionFilterRequest;
import io.testinium.devicepark.model.sessions.DeviceSessionRequest;
import io.testinium.devicepark.model.sessions.Session;
import io.testinium.devicepark.model.sessions.SessionFilter;
import java.util.Collections;
DeviceSessionFilterRequest sessionFilter = DeviceSessionFilterRequest.of(
SessionFilter.SESSION,
"session-123",
SearchOperation.EQUAL
);
PageDto<Session> page = client.sessions().list(
DeviceSessionRequest.builder()
.filters(Collections.singletonList(sessionFilter))
.page(0)
.size(1)
.build()
);
Session session = page.data().stream()
.findFirst()
.orElseThrow(() -> new IllegalStateException("Session was not found"));
if (!"CLOSED".equals(session.state()) || session.videoRecordUrl() == null) {
throw new IllegalStateException("The session recording is not ready yet");
}
System.out.println(session.videoRecordUrl());Java: read and validate the HLS playlist
The following Java 8-compatible method consumes the URL returned by the Java SDK. Pass the Session obtained above and a bearer token supplied by your application's secure server-side authentication component. The Java SDK keeps its own OAuth token internal and does not expose it for use by another HTTP client.
import io.testinium.devicepark.model.sessions.Session;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
static String readHlsPlaylist(Session session, String bearerToken) throws IOException {
if (session.videoRecordUrl() == null) {
throw new IllegalStateException("The session recording is not ready yet");
}
URL hlsUrl = new URL(session.videoRecordUrl());
HttpURLConnection connection = (HttpURLConnection) hlsUrl.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/vnd.apple.mpegurl");
connection.setRequestProperty("Authorization", "Bearer " + bearerToken);
int status = connection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
throw new IOException("HLS playlist request failed with HTTP " + status);
}
StringBuilder playlist = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
playlist.append(line).append('\n');
}
} finally {
connection.disconnect();
}
if (playlist.indexOf("#EXTM3U") != 0) {
throw new IOException("Device Park did not return an HLS playlist");
}
return playlist.toString();
}This verifies and reads the RFC 8216 manifest; it does not decode the video. For playback in a Java desktop, Android or server application, pass session.videoRecordUrl() to an HLS-capable media library and configure that library to send the bearer token for both the manifest and every segment request. If the player cannot attach headers, expose the stream through an authenticated server-side proxy instead of placing Device Park credentials in the client application.
Node.js: play it in a browser
hls.js is a separate browser playback dependency; it is not bundled with the Device Park SDK. The playlist and every segment request must be authorized. Obtain the bearer token through your application's secure backend or existing authenticated session. Never put the Device Park clientSecret in browser code.
npm install hls.jsimport Hls from "hls.js";
import type { Session } from "@device-park/public-sdk";
function playHlsRecording(
session: Session,
bearerToken: string,
video: HTMLVideoElement
): Hls {
if (!session.videoRecordUrl) {
throw new Error("The session recording is not ready yet");
}
const hls = new Hls({
xhrSetup(xhr) {
// hls.js applies this header to the playlist and media-segment requests.
xhr.setRequestHeader("Authorization", `Bearer ${bearerToken}`);
}
});
hls.loadSource(session.videoRecordUrl);
hls.attachMedia(video);
return hls;
}
const video = document.querySelector<HTMLVideoElement>("#recording");
if (!video) {
throw new Error("Video element was not found");
}
const bearerToken = await getBearerTokenFromYourBackend();
const hls = playHlsRecording(session, bearerToken, video);
// Call hls.destroy() when the component or page is disposed.<video id="recording" controls playsinline></video>For a cross-origin player, the Device Park environment must allow CORS GET requests for both the playlist and its segment URLs. Native HLS playback through <video src="..."> can also be used on compatible platforms, but a video element cannot attach a custom bearer header; use it only behind an authorized same-origin proxy or another access mechanism supported by your environment.
The Node.js SDK runs on the trusted server side. A browser should request a short-lived playback token or an authorized proxy URL from that server; it must not receive the clientId and clientSecret used to build DeviceParkApiClient.
Operational notes
- videoRecordUrl === null means the stream is not available yet, recording was not enabled, or access is no longer available.
- A closed recording playlist ends with #EXT-X-ENDLIST. A player can reload a playlist without that tag to discover newly appended segments.
- Respect dataAccessEndDate; do not assume recording access is permanent.
- Use screenRecords(...) for segment metadata and filtering, and use videoRecordUrl for playback.
Verify your integration
- Start a session with videoRecording(true), perform a short interaction and stop the session.
- List the session until its state is CLOSED and videoRecordUrl is not null. Use a bounded retry interval; do not poll indefinitely.
- Request videoRecordUrl with Accept: application/vnd.apple.mpegurl and valid authorization.
- Confirm an HTTP 200 response, the application/vnd.apple.mpegurl content type and a response body beginning with #EXTM3U.
- Start playback and confirm that the playlist's media-segment requests also return HTTP 200. A successful manifest request alone does not prove that segment authorization is configured correctly.
- Confirm that a completed recording can play to the end and that seeking works as expected.
If the manifest succeeds but the video does not start, inspect the segment requests first. HTTP 401 or 403 usually indicates that the player did not forward authorization; a browser CORS error means the Device Park environment or proxy must permit the playlist and segment origins.
Next Step
Release the allocation after all planned sessions and evidence collection are complete.