Preview
Daytona provides preview URLs for accessing services running in your sandboxes. Any process listening for HTTP traffic on ports 3000 - 9999 can be previewed through a generated URL.
Daytona supports two types of preview URLs, each with a different authentication mechanism:
- Standard preview URL uses the sandbox ID in the URL and requires a token sent via header
- Signed preview URL embeds the authentication token directly in the URL, requiring no headers
Authentication
If a sandbox has its public property set to true, preview links are publicly accessible without authentication. Otherwise, authentication is required. The authentication mechanism depends on the preview URL type.
Standard preview URL
The standard preview URL includes your sandbox ID in the URL and provides a separate token for authentication via the x-daytona-preview-token request header.
URL structure: https://{port}-{sandboxId}.{daytonaProxyDomain}
The token resets automatically when the sandbox restarts. Any previously issued standard preview tokens become invalid. Call the get_preview_link() method again after starting the sandbox to obtain a fresh token. Use standard preview URLs for programmatic access and API integrations where you control the HTTP headers.
preview_info = sandbox.get_preview_link(3000)
print(f"URL: {preview_info.url}")print(f"Token: {preview_info.token}")
# Use with requestsimport requestsresponse = requests.get( preview_info.url, headers={"x-daytona-preview-token": preview_info.token})const previewInfo = await sandbox.getPreviewLink(3000);
console.log(`URL: ${previewInfo.url}`);console.log(`Token: ${previewInfo.token}`);
// Use with fetchconst response = await fetch(previewInfo.url, { headers: { 'x-daytona-preview-token': previewInfo.token }});preview_info = sandbox.preview_url(3000)
puts "Preview link url: #{preview_info.url}"puts "Preview link token: #{preview_info.token}"preview, err := sandbox.GetPreviewLink(ctx, 3000)if err != nil { log.Fatal(err)}fmt.Printf("URL: %s\n", preview.URL)fmt.Printf("Token: %s\n", preview.Token)curl 'https://app.daytona.io/api/sandbox/{sandboxId}/ports/3000/preview-url' \ --header 'Authorization: Bearer <API_KEY>'For more information, see the Python SDK, TypeScript SDK, Ruby SDK, Go SDK, and API references:
Authentication
Authenticate by sending the token in the x-daytona-preview-token header:
curl -H "x-daytona-preview-token: vg5c0ylmcimr8b_v1ne0u6mdnvit6gc0" \ https://3000-sandbox-123456.proxy.daytona.workSigned preview URL
The signed preview URL embeds the authentication token directly in the URL, eliminating the need for separate headers. You can set a custom expiry time for the token (defaults to 60 seconds). The token persists across sandbox restarts until it expires. Tokens can be revoked manually before expiry if needed.
URL structure: https://{port}-{token}.{daytonaProxyDomain}
Use signed preview URLs when sharing links with users who cannot set custom headers, embedding previews in iframes or emails, or creating time-limited shareable links.
# Create a signed preview URL that expires in 3600 seconds (1 hour)signed_url = sandbox.create_signed_preview_url(3000, expires_in_seconds=3600)
print(f"URL: {signed_url.url}") # Token is embedded in the URLprint(f"Token: {signed_url.token}") # Can be used to revoke access
# Use directly - no headers neededimport requestsresponse = requests.get(signed_url.url)
# Revoke the token before expiry if neededsandbox.expire_signed_preview_url(3000, signed_url.token)// Create a signed preview URL that expires in 3600 seconds (1 hour)const signedUrl = await sandbox.getSignedPreviewUrl(3000, 3600);
console.log(`URL: ${signedUrl.url}`); // Token is embedded in the URLconsole.log(`Token: ${signedUrl.token}`); // Can be used to revoke access
// Use directly - no headers neededconst response = await fetch(signedUrl.url);
// Revoke the token before expiry if neededawait sandbox.expireSignedPreviewUrl(3000, signedUrl.token);# Create a signed preview URL that expires in 3600 seconds (1 hour)signed_url = sandbox.create_signed_preview_url(3000, 3600)
puts "URL: #{signed_url.url}"puts "Token: #{signed_url.token}"daytona preview-url <sandbox-name> --port 3000 --expires 3600curl 'https://app.daytona.io/api/sandbox/{sandboxId}/ports/3000/signed-preview-url?expiresInSeconds=3600' \ --header 'Authorization: Bearer <API_KEY>'For more information, see the Python SDK, TypeScript SDK, Ruby SDK, and API references:
create_signed_preview_url (Python SDK)
getSignedPreviewUrl (TypeScript SDK)
Authentication
The token is embedded in the URL itself, so no additional headers are required:
curl https://3000-<value>.proxy.daytona.workWarning page
When opening a preview link in a browser for the first time, Daytona displays a warning page. This warning informs users about potential risks of visiting the preview URL and only appears when loading the link in a browser.
To skip the warning page:
- Send the
X-Daytona-Skip-Preview-Warning: trueheader - Upgrade to Tier 3
- Deploy a custom preview proxy