This is how the YouTube Lounge API local-network pairing process looks like on a Samsung TV:
- The device discoveres the TV via SSDP/MDNS on the local network
- The device sends a request to
/ws/app/YouTube
to see if the YT app is available/running:
GET /ws/app/YouTube HTTP/1.1
Host: [tv_ip]:8080
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
API-Version: v1.00
Content-type: text/xml
Date: Sat, 03 Apr 2021 08:25:03 GMT
Server: WebServer
Content-Length: 348
<?xml version="1.0" encoding="UTF-8"?>
<service xmlns="urn:dial-multiscreen-org:schemas:dial" dialVer="2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<name>YouTube</name>
<options allowStop="true"/>
<state>stopped</state>
<version>2.1.498</version>
<link rel="run" href="run"/>
<additionalData>
<testYWRkaXR>c0ef1ca</testYWRkaXR>
</additionalData>
</service>
- The device starts YouTube on the TV by sending a
POST
request to/ws/app/YouTube
, and in the body specifies apairingCode
, which is a random UUID generated by the device:
POST /ws/app/YouTube HTTP/1.1
Host: [tv_ip]:8080
Content-Length: 22
pairingCode=[random_uuid]&theme=cl
HTTP/1.1 201 Created
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
API-Version: v1.00
Content-type: text/html
LOCATION: http://[tv_ip]:8080/ws/apps/YouTube/run
Date: Sat, 03 Apr 2021 08:28:24 GMT
Server: WebServer
Content-Length: 45
http://[tv_ip]:8080/ws/apps/YouTube/run
- The device gets a
lounge_token
from the Leanback API using the random-generatedpairingCode
fromStep 3.
:
POST /api/lounge/pairing/get_screen HTTP/1.1
Host: www.youtube.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 49
pairing_code=[redacted]&theme=cl
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Date: Sat, 03 Apr 2021 08:31:28 GMT
Expires: Sat, 03 Apr 2021 08:31:28 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
X-XSS-Protection: 1; mode=block
Server: GSE
Alt-Svc: h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Accept-Ranges: none
Vary: Accept-Encoding
Content-Length: 652
{
"screen": {
"accessType": "permanent",
"screenId": "[readacted]",
"dialAdditionalDataSupportLevel": "full",
"loungeTokenRefreshIntervalMs": 1123200000,
"loungeToken": "[readacted]",
"clientName": "tvhtml5",
"shortLivedLoungeToken": {
"refreshIntervalMs": 1200000,
"lifespanMs": 3600000,
"loungeTokenType": "one_hour",
"value": "[readacted]"
},
"name": "YouTube on TV",
"expiration": 1618561888899,
"deviceId": "[readacted]"
}
}
- The device can quit the YouTube app on the TV by sending a
DELETE
requsest to/ws/app/YouTube/run
:
DELETE /ws/app/YouTube/run HTTP/1.1
Host: [tv_ip]:8080
Content-Length: 0
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
API-Version: v1.00
Content-Length: 0
Date: Sat, 03 Apr 2021 14:23:20 GMT
Server: WebServer
Actually, if the YouTube app is already running, the lounge_token
can be simply obtained from /ws/app/YouTube
:
GET /ws/app/YouTube HTTP/1.1
Host: [tv_ip]:8080
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
API-Version: v1.00
Content-type: text/xml
Date: Sat, 03 Apr 2021 08:25:03 GMT
Server: WebServer
Content-Length: 348
<service xmlns="urn:dial-multiscreen-org:schemas:dial" xmlns:atom="http://www.w3.org/2005/Atom" dialVer="2.2">
<name>YouTube</name>
<options allowStop="true"/>
<state>running</state>
<version>2.1.498</version>
<link rel="run" href="run"/>
<additionalData>
<testYWRkaXR>c0ef1ca</testYWRkaXR>
<screenId>[redacted]</screenId>
<theme>cl</theme>
<deviceId>[redacted]</deviceId>
<loungeToken>[redacted]</loungeToken>
<loungeTokenRefreshIntervalMs>1500000</loungeTokenRefreshIntervalMs>
</additionalData>
</service>