The External Control Protocol (ECP) enables a Roku device to be controlled over a local area network by providing a number of external control services. The Roku devices offering these external control services are discoverable using SSDP (Simple Service Discovery Protocol). ECP is a simple RESTful API that can be accessed by programs in virtually any programming environment.
SSDP (Simple Service Discovery Protocol)
SSDP is an industry IETF standard network protocol for discovery of local area network services. Roku devices advertise their external control services using the multicast SSDP so that programs can discover the IP address of Roku devices in the area. There is a standard SSDP multicast address and port (188.8.131.52:1900) used for local area network communication. The Roku device responds to M-SEARCH queries on this IP address and port.
To query for a Roku device IP address, send the following HTTP request to 184.108.40.206 port 1900:
M-SEARCH * HTTP/1.1
Note there must be a blank line at the end of the file above. If you put the above request into a file such as roku_ecp_req.txt, you can issue the following command on most Linux machines to test the request:
% ncat 220.127.116.11 1900 < roku_ecp_req.txt
If you view the response using Wireshark, and filter on port 1900, you can see the Roku device response (Ncat has trouble receiving multicast traffic, so viewing the response using Ncat does not work). The response has the following format:
HTTP/1.1 200 OK
If you get a 200 status response, the Location header is valid. You can parse out the URL for the Roku device external control services from the Location header. The Roku device serial number is contained in the USN line after uuid:roku:ecp. Note that if there are multiple Roku devices in your local area network, you will get multiple responses. Your program could keep a map of USNs to location URLs, and allow the user to select which Roku device on the network to control. We recommend you let the user assign names to the USNs.
When parsing headers in the response, in accordance with the UPnP Device Architecture specification, field names should not be treated as case sensitive. That means that, for example, the Location header may begin with either "Location:" or "LOCATION:" or "location:", and so forth.
Please note the Cache-Control header. Roku devices multicast NOTIFY messages periodically (approximately every 20 minutes). It is safe to assume the unit is no longer available if you have not received a new NOTIFY message before the Cache-Control max-age time expires.
External Control Service Commands
The external control services provided by ECP are included in a simple RESTful API accessed using HTTP on port 8060. Once you have the Roku device IP address, you can issue the following external control service commands to the Roku device.
General ECP commands
|Returns a map of all the channels installed on the Roku device paired with their application ID. This command is accessed using an HTTP GET.|
|Returns a child element named 'app' that identifies the active application, in the same format as 'query/apps'. If no application is active, such as when the user is in the homescreen, the element only contains "Roku". If a screensaver is active, a second element will be included containing "screensaver". If the screensaver is an application-provided or plug-in screensaver, the same information is provided as 'query/apps'. If the screensaver is active, but is not running (such as due to system limitations), the screensaver element contains "black". This command is accessed using an HTTP GET.|
|Equivalent to pressing the remote control key identified after the slash. This command is sent using an HTTP POST with no body.|
|Equivalent to releasing the remote control key identified after the slash. This command is sent using an HTTP POST with no body.|
|Equivalent to pressing down and releasing the remote control key identified after the slash. You can also use this command, and the keydown and keyup commands, to send keyboard alphanumeric characters when a keyboard screen is active, as described in Keypress Key Values. This command is sent using an HTTP POST with no body.|
Launches the channel identified by appID. You can follow the appID with a question mark and a list of URL parameters to be sent to the application as an associative array, and passed to the RunUserInterface() or Main() entry point. This command is sent using an HTTP POST with no body.
The launch command should not be used to implement deep-linking to an uninstalled channel, because it will fail to launch uninstalled channels. Use the install command instead for uninstalled channels.
|Exits the current channel, and launches the Channel Store details screen of the channel identified by appID. You can follow the appID with a question mark and a list of launch parameters to be sent to the application as an associative array, and passed to the RunUserInterface() or Main() entry point. If launch parameters are given, the channel is launched immediately after the user installs the channel, and deep-links to content provided in the launch parameters. This command is sent using an HTTP POST with no body.|
|Retrieves device information similar to that returned by roDeviceInfo. This command is accessed using an HTTP GET.|
Returns an icon corresponding to the application identified by appID. The binary data with an identifying MIME-type header is returned. This command is accessed using an HTTP GET.
Sends custom events to the current application. It takes a user defined list of name-value pairs sent as query string URI parameters. The external control server places these name-value pairs into an associative array, and passes them directly through to the currently executing channel script using a Message Port attached to a created roInput object. Input Command Conventions includes detailed recommendations on how to pass your data. Messages of type roInputEvent have a GetInfo() method that will obtain the associative array. The arguments must be URL-encoded. This command is sent using an HTTP POST with no body.
|Enables an external client to drive the Roku Search UI to find and (optionally) launch content from an available provider. This command does not return any data back to the external client and is not intended to power a custom UI based on Roku data. See search Examples below.|
Roku TV ECP commands
Roku TV devices additionally support the following external control services.
|Returns information about the TV channel / line-up available for viewing in the TV tuner UI.|
|Returns information about the currently tuned TV channel.|
|Launch the TV tuner UI.|
Can optionally be passed a TV channel parameter of the form "ch=1.1" to tune to the specified TV channel number.
Input Command Conventions
As the firmware simply marshals the arguments to the input command and passes them to the channel script, the forms below compose a conventional way to communicate input from several common input device types.
Sensor Input Values
There are four sensor input values to report: accelerometer, orientation, gyroscope (rotation), and magnetometer (magnetic). All except orientation are vectors in a cartesian coordinate system relative to the device in its default orientation:
- +x = to the right of the front face of the device (usually the short side)
- +y = to the top of the front face of the device (usually the long side)
- +z = out of the front face of the device (toward the viewer)
The orientation coordinate system is relative to the point on the surface of the Earth between the device and the center of the Earth:
- +x = east
- +y = north
- +z = towards the center of the Earth (down)
The type in all such cases is a string representation of a signed floating point number, with or without an explicit decimal, and with or without a signed integer exponent following the letter E. A missing decimal will be presumed after the rightmost present digit, and a missing exponent will be presumed 0.
indicates: acceleration in each dimension relative to free fall
names: acceleration.x, acceleration.y, acceleration.z
indicates: angular displacement from flat/level and true (or magnetic?) north.
names: orientation.x, orientation.y, orientation.z
notes: Accurate indication of this is not generally possible without correlation with other sensors or assumptions. Devices make assumptions to flip the display, for example, that assume that the device is usually not moving (much) so that all force is simply opposed to gravity, and that can be assumed to be the "up" direction. Deviation from magnetic north depends on a magnetometer, and deviation from true north also depends on geolocation.
indicates: angular rotation rate about each axis using the right hand rule for sign
names: rotation.x, rotation.y, rotation.z
indicates: magnetic field strength
names: magnetic.x, magnetic.y, magnetic.z
Touch and Multi-Touch
Touch and Multi-Touch commands take the same form. The resource is the same "input" as all other generic input commands.
Each action is decomposed to an argument in each dimension (of 2, x and y with the same orientation as for the sensor inputs, with origin in lower left). There is an additional "op" argument which can specify down, up, press (down and up), move, or cancel. Each input is also qualified with a pointer id that indicates the initial order of down touches in a multi-touch gesture.
Several such points can be specified in a single POST, especially a move, but a full triad of x, y, and op arguments should be sent, and expected for each point, within a POST that contains any of them.
Additional Input Values
Other information you might want to pass using the input command may include:
- sensor accuracy
- geolocation (from GPS)
- device-provided derivations of above sensor readings, for example "shake" from accelerometer, or "pinch" from multi-touch
External Control Protocol Examples
The following are some example ECP commands sent via the curl command.
The following command gets a list of channels and their corresponding app ids.
$ curl http://192.168.1.134:8060/query/apps
<app id="11">Roku Channel Store</app>
<app id="13">Amazon Video on Demand</app>
<app id="26">Free FrameChannel Service</app>
The query/active-app command if the user is in the homescreen.
The query/active-app command if the user is in the homescreen but the default screensaver is active.
<screensaver id="55545" type="ssvr" version="2.0.1">Default screensaver</screensaver>
The query/active-app command if the user is in the Netflix app.
<app id="12" type="appl" version="4.1.218">Netflix</app>
The query/active-app command if the user is in the Roku Media Player with an active screensaver.
The following command simulates a user hitting the "Home" button
$ curl -d ''
The following commands move the cursor to the far left by holding down the Left key for 10 seconds
$ curl -d '' http://192.168.1.134:8060/keydown/left
$ sleep 10
$ curl -d ''
The following command will launch the dev app on the box. The simplevideoplayer app that comes with the SDK will process the "url" and "streamformat" parameters and launch the roVideoScreen to play the passed in video. We assume simplevideoplayer is installed as the side-loaded developer application.
$ curl -d '' 'http://192.168.1.134:8060/launch/dev?streamformat=mp4&url=http%3A%2F%2Fvideo.ted.com%2Ftalks%2Fpodcast%2FVilayanurRamachandran_2007_480.mp4'
The following command will launch the dev app on the box. The launchparams app that comes with the SDK will process the "contentID" and "options" parameters and display them on a SpringBoard page. We assume launchparams is installed as the side-loaded developer application. This technique is a useful way to create "clickable" ads that launch a springboard page for a particular title in your channel. Roku now supports clickable ads on the home screen as well.
$ curl -d '' 'http://192.168.1.134:8060/launch/dev?contentID=my_content_id&options=my_options'
launch parameters for the Channel Store app (channel ID 11)
The Channel Store app (channel ID 11) can be passed a "contentID" parameter with the channel ID of a target application.
The following command will launch the channel store app (11) on the box with a contentID equal to 14 (the MLB app).
You can get the plugin ID for your app using the /query/apps example above, which returns the installed apps on a Roku player.
(You should test that the channel is installed before using the launch command, and use the install command for uninstalled channels).
This technique would be useful in creating clickable ads in a free "Lite" version of a paid app.
When a user clicks on the ad, the channel store page to purchase the full version could be launched.
$ curl -d '' '/launch/11?contentID=14'
launch parameters for the Roku TV Tuner app (channel ID tvinput.dtv)
The TV Tuner app can be launched and can optionally be passed a "ch" parameter with the channel number to tune to.
The following command will launch the TV tuner UI and display channel 1.1 (assuming that channel is available).
$ curl -d '' '/launch/tvinput.dtv?ch=1.1'
Below is an example query/device-info request and response.
$ curl '
<user-device-name>My Roku 3</user-device-name>
This following command will return the icon for the channel with id 12 (Netflix).
The response will be raw binary picture data, after HTTP headers, including one with the MIME type of the picture data.
$ curl 'http://192.168.1.134:8060/query/icon/12' > img.png
The following command passes three components of acceleration through to the channel app. All query string parameters are passed to the currently running app. The remote app and the currently running app just need to agree on the query string parameters and any communication can be developed.
$ curl -d '' 'http://192.168.1.134:8060/input?acceleration.x=0.0&acceleration.y=0.0&acceleration.z=9.8'
The following command indicates that a touch at the given x and y has touched down on the screen.
$ curl -d '' 'http://192.168.1.134:8060/input?touch.0.x=200.0&touch.0.y=135.0&touch.0.op=down'
The content title, channel name, person name, or keyword to be searched.
If title is specified, it will be automatically used for the keyword value if keyword is not specified.
|title||Optional||The exact content title, channel name, person name, or keyword to be matched (ASCII case-insensitive).|
one of "movie", "tv-show", "person", "channel", or "game"
This parameter is recommended as otherwise the search results are unconstrained and may cause the desired item to not be found due to result limits.
A TMS ID for a movie, TV show, or person.
If known, this parameter is recommended to be passed in conjunction with the keyword and type parameters as this should most likely provide the desired search result.
A season number for a TV show (series), e.g. 1, 2, 3, ...
If specified for a tv-show search, and the TV show is found, the specified season will be picked in the Seasons list to be launched.
If not specified or not found, the default (typically most recent) season will be selected.
|show-unavailable||Optional||Allows the general keyword search results to include upcoming movie / tv-shows that are not currently available on Roku.|
|match-any||Optional||If there are multiple results matching the query, automatically selects the arbitrary first result.|
If this is not specified, the search will stop if the results do not indicate a unique result.
|provider-id||Optional||One or more Roku channel IDs specifying the preferred/target provider.|
If specified, and the search results are available, the first provider available will be selected (and launched if so specified).
The value may be specified as a comma separated list. E.g. "12,13" indicates that Netflix should be used (if available), else Amazon Video (if available).
|provider||Optional||One or more Roku channel titles specifying the preferred/target provider. If specified, and the search results are available, the first provider available will be selected.|
The value may be specified as a comma separated list. E.g. "Amazon Video, VUDU" indicates that Amazon Video should be used (if available), else VUDU (if available).
Provider names are must be a full title match (case-insensitive) against the user's installed channels to be recognized.
|launch||Optional||Specifies that if the search content is found and a specified provider is available, the provider channel should be launched.|
Below is an example of the Roku TV query/tv-channels response.
$ curl '
Below is an example of the Roku TV query/tv-active-channel response.
$ curl '
<program-description>The team will travel all around the world in order to shut down a global crime ring.</program-description>
Deeplinking to a channel
One of the most common ways that channel developers encounter ECP is deep linking. Deep linking lets other parts of the system launch a particular piece of content via parameters passed to the channel at launch time. Here is a link on how to implement deep linking in your channel. Deep Linking
The standard for deep linking uses parameters:
|contentID||Partner defined unique identifier for a specific piece of content||Any value < 255 characters long and not using "&" or other characters that are not URL encoded.|
|mediaType||Parameter to give context to the type of contentID passed.|
"series","season", "episode", "movie", "short-form", "special" and "live"
You trigger deep linking by doing an HTTP post to port 8060 on your Roku device. The general form is
http://<IP of Roku>:8060/launch/[dev | channel ID]?contentId=<content ID>&MediaType=<mediaType>
The first example will launch the current sideloaded application and deep link to a series contentID 1234. Notice the -d ' ' which forces it to do a http post.
curl -d '' '
This example shows using the install command to launch a production channel with the ID 8378
curl -d '' 'http://192.168.1.114:8060/install/8378?contentid=MV005011860000&MediaType=movie'
- You can also just launch the channel without deep linking by removing the arguments from the URL.
- You can find the channel ID of a production channel by using one of the two deep link test tools
Installing a channel with ECP
just like deep linking you can install a channel with an HTTP post. In this case, the format is
http://<IP or Roku>:8060/install/<channel ID>
Keypress Key Values
When the current screen on the Roku box includes an on-screen keyboard, any keyboard character can be sent via the keyup, keydown, and keypress commands. The key parameter can either be a key name, such as the name of a button on a remote control, or a printable character value specified with the prefix "Lit_".
Printable ASCII character code values can be transmitted "as-is" with the "Lit_" prefix. For example, you can send a 'r' with "Lit_r". In addition, any UTF-8 encoded character can be sent by URL-encoding it. For example, the euro symbol can be sent with "Lit_%E2%82%AC".
There are even some keys you can send that are not available on any physical remote. Enter is for completing keyboard entry fields, such as search fields (it is not the same as Select). Search is useful for short-cutting directly to search screens.
The following are the key names that are recognized by ECP:
Roku devices that support the "Find Remote" support:
Note that query/device-info includes a supports-find-remote flag that indicates whether the Roku device supports FindRemote.
However this does not specifically indicate that the device has a paired remote that supports "Find remote" as well.
Some Roku devices, such as Roku TVs, also support:
Roku TV devices also support changing the channel when watching the TV tuner input:
Roku TV devices also support keys to set the current TV input UI:
Example: On the on-screen keyboard, the string 'roku' can be sent via the following commands:
$ curl -d '' http://192.168.1.134:8060/keypress/Lit_r
$ curl -d '' http://192.168.1.134:8060/keypress/Lit_o
$ curl -d '' http://192.168.1.134:8060/keypress/Lit_k
$ curl -d '' http://192.168.1.134:8060/keypress/Lit_u
Note that with the launch command, anyone could write a program that could pass arbitrary parameters to your BrightScript channel. It is important that you validate any parameters that are passed to your program, and check what they may do to your program flow. The launch command can be very powerful to provide all kinds of interaction between network devices and your program. We envision catalogs browsed on the Internet that could instantly be watched in your channel on the Roku. The door is open to many creative uses.
But if you prefer to shut this door on your channel, you can choose to not process any passed parameters. This will mean external control programs could launch your channel, but they could not change the program flow within your channel.
The SDK includes a sample External Control Protocol application that requires only glibc to compile. The program is self contained in the /examples/rokuExternalControl.c file of the SDK. You can compile and run it with the following commands:
% cd SDK_directory
% gcc ./examples/rokuExternalControl.c –o rokuExternalControl
On Windows, it can be compiled with the following line:
% cl /D "WIN32" rokuExternalControl.c
The program first uses SSDP to query for Roku devices in the local area network. The first Roku device that responds is the one to which commands are sent. All requests and responses are printed to stdout so that you can easily follow what the program is doing. The program next moves the cursor to the home screen and highlights the "Netflix" program. It does this by sending the Home key command, and then holding down the left key for twelve seconds. Then it sends the Right key three times. After keeping the "Netflix" program highlighted for five seconds, the program launches the simplevideoplayer application with url and streamformat as keys in the associative array passed to the Main() entry point. The simplevideoplayer application immediately launches the roVideoScreen when launched with an associative array containing valid url and streamformat keys.
With ECP, you have complete control of your Roku device over the network. We can't wait to see what kind of solutions our developer community can create. The sample C program can be quickly modified to run in a variety of environments including Firefox, IE, and other browser plugins, iPhone, iPad, and other mobile device environments.
The SDK also includes a couple of Java applications. There is an Android remote application in examples/source/ecp_client/android_remote, and a simple application to find Roku devices on the local area network in examples/source/ecp_client/Roku_Finder.
DIAL (Discovery and Launch)
The Roku platform supports the DIAL (Discovery and Launch) protocol. DIAL is a simple network protocol for discovering first screen devices, and applications from a second screen (such as a mobile iOS or Android application,) and for launching first screen applications on the first screen device from the second screen app. In the context of the Roku platform, the first screen device is the Roku device itself. A first screen application is a DIAL-aware channel installed on the Roku device. Complete details of the DIAL specification can be found here:
Many current Roku developers are familiar with the Roku external control protocol (ECP) which includes functionality similar to DIAL. An experienced Roku developer may thus fairly ask the question "why do I need DIAL?" One reason is that you may already have a DIAL based second screen implementation for use with other platforms. DIAL support on the Roku platform means that you don’t need to add a second protocol to your current application for discovery and launch.
The Roku DIAL SDK contains detailed documentation of Roku DIAL support, as well as BrightScript, Android, and iOS sample applications. In DIAL parlance, the BrightScript sample is the first screen application, and the Android and iOS apps are the second screen applications. These sample applications should help you get started with your own Roku DIAL support.