Develop Chrome Sender App for Cast v2

This overview describes how to build a Google Cast sender application for Chrome using the Google Cast SDK.

In this document, sender application or Google Cast application refers to a web (HTML/JavaScript) app running inside a Chrome browser on a sender device. Receiver application refers to an HTML/Javascript application running on Chromecast or other Google Cast devices.


The Chrome Sender SDK supports the Chrome browser on a Mac, Windows, Linux, ChromeOS, Android and iOS devices. (For native mobile Cast applications see Android Apps and iOS Apps instead.)

The Google Cast Chrome Sender SDK is provided natively in Chrome.



Other than registering your application and device, no special setup steps are required to use the Google Cast Chrome Sender SDK. As long as you have the latest version of Chrome, it is possible for your web content to access and use the SDK.

To register your application and device:

  • Follow the steps at Registration. Once you have your application ID, you're ready to develop your application.


User access to enable Cast functionality is provided via the Chrome menu:

The Chome menu showing the
Cast item highlighted

Users can also optionally install the Google Cast toolbar icon Shows a TV screen
receiving a signal in order to get direct access to Google Cast functionality without having to use the Chrome menu.

Updates to Google Cast occur automatically for all users, and provide fixes, user-facing features, and SDK capabilities. Updates are backwards-compatible, and should be transparent to your site.

Chrome beta channel

A public beta channel for Chrome is also available. New versions of Chrome are pushed to the beta channel prior to a full release; the beta channel is also updated more often than the stable channel. This gives developers (and passionate early adopters) advance access to new features, and allows you to ensure that your site works with upcoming versions of Chrome.

To use the public beta channel:

  • Install the beta version of Chrome.
  • To report issues, with the Google Cast toolbar icon installed, right-click on the Cast toolbar icon and choose "Report an issue". We can’t respond individually to most feedback, but we greatly value the input on the beta channel.
  • Before pushing updates to your live site, ensure that you test with the current stable version of Chrome. Most visitors to your site will have the stable version of Chrome installed, and if you depend on beta-only features, users with the stable version will be impacted.


For your app to implement the features of Google Cast, it needs to know the location of the Google Cast Chrome Sender API library. All pages of your app must refer to the library as follows:

<script type="text/javascript"

A Google Cast Chrome Sender app may be described in several phases. This overview describes the code for each phase.

Non-JavaScript player

Your sender application's properties and functions may be accessed or used with a non-JavaScript player such as Flash or Silverlight. These frameworks provide methods that hook into your JavaScript sender code and let you pass parameters and handle events in the Flash or Silverlight player.

For example, the ActionScript method, parameter-1, parameter-2) can be used to hook into your media control methods, such as initializeCastApi. Likewise, the ActionScript method ExternalInterface.addCallback("EVENT", ActionScriptAction) can be used to handle events like button clicks and progress bar updates.

See your framework's documentation for more information about hooking into your sender's JavaScript code.


The Google Cast Chrome Sender SDK defines its top-level namespace as chrome.cast.*. The namespace represents the following:

  • Methods or functions that invoke operations on the API and their associated callbacks
  • Data objects that are passed to and from methods and callbacks
  • Event listeners for listener functions in the API

Review the Google Cast Chrome Sender API Reference for a complete description of the namespace.


To determine if the API is available and initialize it, you can provide the callback function window['__onGCastApiAvailable'] before the Cast API loads. It is invoked with loaded == true if the API loads, or with errorInfo when load fails.

window['__onGCastApiAvailable'] = function(loaded, errorInfo) {
  if (loaded) {
  } else {

Another way to initialize the API (still supported) is, upon page load set a timer, wait for the DOM to complete loading and for the Chrome Sender API to become available. For example, check for the API's availability with the following code:

if (!chrome.cast || !chrome.cast.isAvailable) {
  setTimeout(initializeCastApi, 1000);

Then, you initialize the API as follows:

initializeCastApi = function() {
  var sessionRequest = new chrome.cast.SessionRequest(applicationID);
  var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
  chrome.cast.initialize(apiConfig, onInitSuccess, onError);

At first you create a sessionRequest object based on your own applicationID, if you are using a registered receiver application. If you are using the default receiver, for which no registration is required, you use a constant predefined by the Chrome Sender SDK, as shown below, instead of the applicationID:

var sessionRequest = new chrome.cast.SessionRequest(

Next, you define an ApiConfig object using the sessionRequest object, along with two callback functions, namely sessionListener and receiverListener. Then you call the chrome.cast.initialize method by passing the ApiConfig object.

The call to the method chrome.cast.initialize has two callbacks, one for success, one for error. The sessionListener function is discussed further in the Session management section, below. Here, assuming the initialize function returns success, your application is ready to use the Cast features.

Device selection

Device selection is managed by the Chrome's media router component. The Cast features in your app are available to your users once the initialize call returns success and the receiverListener callback function returns with the availability of device(s). Here's the receiverListener callback:

function receiverListener(e) {
  if( e === chrome.cast.ReceiverAvailability.AVAILABLE) {

The receiverListener callback only reports whether Cast devices are available; it does not report which devices are available. The available devices are known only to Chrome's Media Router component.

The user performs device selection through requestSession API call. That action must be triggered by clicking on the Google Cast icon, which must display in the media control bar, as described in the User Experience Guidelines. When the user clicks on the Cast icon, your app can request a session, which automatically triggers Chrome to present a list of Cast devices to connect.

This is one of the two ways for your app to get hold of a session object. Another is to connect to an existing session, discussed in Session management, below.


When the user clicks the Cast icon, launch your application and create a Cast session, as follows:

chrome.cast.requestSession(onRequestSessionSuccess, onLaunchError);

The onRequestSessionSuccess callback function returns a chrome.cast.Session object between your sender app and Cast receiver app for the selected Cast receiver device.

function onRequestSessionSuccess(e) {
      session = e;

The Session object also has a receiver which you can use to display the friendly name of the receiver.

The connection to your receiver doesn't occur until your sender issues its first message, such as loadRequest, described below.

Media control

Now that you have a chrome.cast.Session object, you may load media to the selected Cast device by creating a MediaInfo object for the currentMediaURL, creating a LoadRequest object from it, and then calling the loadMedia method of the session object.

var mediaInfo = new;
var request = new;
   onMediaDiscovered.bind(this, 'loadMedia'),

function onMediaDiscovered(how, media) {
   currentMedia = media;

Upon successful callback of onMediaDiscovered, you get a object, which grants you full media control of PLAY, PAUSE, RESUME, STOP and SEEK for the loaded media.

  • PLAY/RESUME:, success, error);
  • PAUSE: currentMedia.pause(null, success, error);
  • STOP: currentMedia.stop(null, success, error);
  • SEEK:, success, error);

Media status

During media playback various events occur, so you need to add the following event listener when the media is successfully loaded.

function onMediaDiscovered(how, media) {

When events such as pause, play, resume or seek occur, you need to act on them and synchronize between your sender app and the receiver app on the Cast device. See also, Status updates for more information.

Session management

When your app launches in response to a user action, a new Cast session is created, as described in Launch, above. You can get hold of an existing session, using the sessionListener callback function, as follows:

function sessionListener(e) {
  session = e;
  if ( != 0) {

This enables your app to auto-join an existing session on any page of your app, manage a session’s lifecycle, and ultimately provide a seamless user experience in your app. It's useful for those situations when the session is created apart from the initial session request.

There are three actions other than requesting the session that will generate a Cast session and fire the sessionListener:

  • The user clicks the Cast icon in the browser toolbar to launch a new session. For example, casting to a different device.
  • A user can mirror any Chrome tab to a Cast device. While mirroring, if the user lands on your site, for which you have implemented a Cast app, tab mirroring will automatically trigger a new Cast session instead of trying to put the browser in mirroring mode.
  • If the user is already casting the current app, then navigates to a page in the same domain within the same tab (for example, going from one video to another), the session in this case is a handle to an existing session that is auto-joined, enabling a continuous experience across page transitions on a site.

However, as described in Launch above, the connection to a new session doesn't occur until your sender issues its first message.

For disconnection, as when the user clicks the "stop casting" button from the Cast dialog, you must define an update listener for session state changes. Call the Session.addUpdateListener method in the sessionListener you created for session management (above). In your listener, check if Session.status is disconnected, and if so, update the local player to a disconnected state. For example:

if (session.status !== chrome.cast.SessionStatus.CONNECTED) {
    console.log('SessionListener: Session disconnected');
    // Update local player to disconnected state


To stop casting, you need a valid Session object. Then call the session's stop function:

function stopApp() {
  session.stop(onSuccess, onError);

Using the Tracks APIs

A track can be a text (subtitle or caption) object, or an audio or a video stream object. The Tracks APIs let you work with these objects in your application.

A Track object represents a track in the SDK. You can configure a track and assign a unique ID to it like this:

var englishSubtitle = new, // track ID;
englishSubtitle.trackContentId = 'https://some-url/caption_en.vtt';
englishSubtitle.trackContentType = 'text/vtt';
englishSubtitle.subtype =; = 'English Subtitles';
englishSubtitle.language = 'en-US';
englishSubtitle.customData = null;

var frenchSubtitle = new, // track ID;
frenchSubtitle.trackContentId = 'https://some-url/caption_fr.vtt';
frenchSubtitle.trackContentType = 'text/vtt';
frenchSubtitle.subtype =; = 'French Subtitles';
frenchSubtitle.language = 'fr';
frenchSubtitle.customData = null;

var frenchAudio = new, // track ID;
frenchAudio.trackContentId = 'trk0001';
frenchAudio.trackContentType = 'audio/mp3';
frenchAudio.subtype = null; = 'French Audio';
frenchAudio.language = 'fr';
frenchAudio.customData = null;

A media item may have multiple tracks; for example, it can have multiple subtitles (each for a different language) or multiple alternative audio streams (for different languages).

MediaInfo is the class that models a media item. To associate a collection of Track objects with a media item, you update its tracks property. This association needs to be made before the media is loaded to the receiver:

var tracks = [englishSubtitle, frenchSubtitle, frenchAudio];
var mediaInfo = new;
mediaInfo.contentType = 'video/mp4';
mediaInfo.metadata = new;
mediaInfo.customData = null;
mediaInfo.streamType =;
mediaInfo.textTrackStyle = new;
mediaInfo.duration = null;
mediaInfo.tracks = tracks;

You can set the active tracks in the media Load request.

You can also activate one or more tracks that were associated with the media item, after the media is loaded, by calling EditTracksInfoRequest(opt_activeTrackIds, opt_textTrackStyle) and passing the IDs of the tracks to be activated in opt_activeTrackIds. Note, both parameters are optional and you may choose which, active tracks or styles, to set at your discretion. For example, here is how to activate the French subtitle (2) and French audio (3):

var activeTrackIds = [2, 3];
var tracksInfoRequest = new;
media.editTracksInfo(tracksInfoRequest, successCallback, errorCallback);

To remove all audio or video tracks from the current media, simply set mediaInfo.tracks=null (an empty array) and reload the media.

To remove all text tracks from the current media (for example, turning off subtitles), do one of the following:

  • Update var activeTrackIds = [2, 3]; (shown previously) so it includes [3] only, the audio track.
  • Set mediaInfo.tracks=null. Note that it's not necessary to reload the media to turn off text captions (track.hidden). Sending an activeTracksId array that doesn't contain a previously enabled trackId disables the text track.

Styling text tracks

TextTrackStyle is the object that encapsulates the styling information of a text track. After creating or updating an existing TextTrackStyle object, you can apply that to the currently playing media item by calling its editTracksInfo method, like this:

var textTrackStyle = new;
var tracksInfoRequest = new;
media.editTracksInfo(tracksInfoRequest, successCallback, errorCallback);

You can track the status of the request with result of the callbacks, either success or error, and update the originating sender accordingly.

Applications should allow users to update the style for text tracks, either using the settings provided by the system or by the application itself.

You can style the following text track style elements:

  • Foreground (text) color and opacity
  • Background color and opacity
  • Edge type
  • Edge Color
  • Font Scale
  • Font Family
  • Font Style

For example, set the text color to red with 75% opacity as follows:

var textTrackStyle = new;
textTrackStyle.foregroundColor = '#80FF0000';

Volume control

The sender app should adhere to the following guidelines for controlling volume:

  • The sender application must synchronize with the receiver so that the sender UI always reports the volume per the receiver. Use the addUpdateListener() callback to maintain the volume on the sender. See Status updates for more information.
  • Sender apps must not set the volume level at a specific, pre-defined level or set the volume level to the sender device's ringer/media volume when the app loads on the receiver.

See Sender volume controls in the Design Checklist for more specific UI guidelines.

Status updates

When multiple senders are connected to the same receiver, it is important for each sender to be aware of the changes on the receiver even if those changes were initiated from other senders.

To this end, your application should register an UpdateListener for that session. If the TextTrackStyle of the current media changes, then all of the connected senders will be notified and the corresponding properties of the current media session, such as activeTrackIds and textTrackStyle of the MediaInfo field will be sent to senders in callbacks. In this case, the receiver SDK does not verify whether the new style is different from the previous one and notifies all the connected senders regardless.

Progress indicator

Showing the playback location with a progress indicator on the sender is a requirement for most apps. The Cast APIs use the Cast media protocol, which optimizes bandwidth consumption for this and other scenarios, so you do not need to implement your own status synchronization. For the proper implementation of a progress indicator for media playback using the APIs, see the CastVideos-chrome sample app.

CORS requirements

For adaptive media streaming, Google Cast requires the presence of CORS headers, but even simple mp4 media streams require CORS if they include Tracks. If you want to enable Tracks for any media, you must enable CORS for both your track streams and your media streams. So, if you do not have CORS headers available for your simple mp4 media on your server, and you then add a simple subtitle track, you will not be able to stream your media unless you update your server to include the appropriate CORS header. In addition, you need to allow at least the following headers: Content-Type, Accept-Encoding, and Range. Note that the last two headers are additional headers that you may not have needed previously.

Sample apps

See the following samples for a completely coded app:

  • Hello Video sample app - demonstrates the essential API objects, methods and event listeners.
  • CastVideos sample app - provides an implementation of an HTML5/Javascript media player that acts as a Chrome sender, is fully compliant with our UX guidelines, and demonstrates typical features such as transition between local playback mode and cast mode, states and progress bar synchronization between the two modes, and auto-join during page reload.