Castjs provides simple events and functions to communicate with Chromecast devices from the browser.
This library works in Chrome, Opera, Brave, Edge and Vivaldi. See it in action on the online demo.

Do you want to support my work? Feel free to donate a β Hot Beverage
Include the library from cdnjs:
<script src="https://cdn.jsdelivr.net/gh/castjs/castjs@v7.0.0/cast.min.js"></script>The Google Cast framework (
cast_sender.js) is automatically loaded if it is not already present on the page.
Make sure you enable CORS on your media resources:
Access-Control-Allow-Origin: *
<button id="cast">Cast</button>
<script src="https://cdn.jsdelivr.net/gh/castjs/castjs@v7.0.0/cast.min.js"></script>
<script>
const cjs = new Castjs();
document.getElementById('cast').addEventListener('click', () => {
if (cjs.available()) {
// Simple example
cjs.cast('https://www.peach.themazzone.com/durian/movies/sintel-1024-surround.mp4');
// Full example with metadata + subtitles
cjs.cast('https://www.peach.themazzone.com/durian/movies/sintel-1024-surround.mp4', {
poster: 'https://castjs.io/media/poster.jpg',
title: 'Sintel',
description: 'Third Open Movie by Blender Foundation',
subtitles: [{
active: true,
label: 'English',
src: 'https://castjs.io/media/english.vtt'
}, {
label: 'Spanish',
src: 'https://castjs.io/media/spanish.vtt'
}]
});
}
});
</script>Almost any Chromium-based browser supports the Cast framework:
Requires HTTPS (or
localhost)
// Default instance
const cjs = new Castjs();
// Custom options
const cjs = new Castjs({
joinpolicy: 'tab_and_origin_scoped', // default
// 'tab_and_origin_scoped' | 'origin_scoped' | 'page_scoped'
receiver: 'CC1AD845', // default media receiver
debug: true // enable debug logs
});cjs.cast(src, metadata) // Start casting
cjs.play() // Resume playback
cjs.pause() // Pause playback
cjs.disconnect() // End session
cjs.time() // Get current time (seconds)
cjs.time(120) // Seek to 2:00
cjs.time(true) // Get formatted time ("02:00")
cjs.duration() // Get duration (seconds)
cjs.duration(true) // Get formatted duration
cjs.volume() // Get volume (0 β 1)
cjs.volume(0.5) // Set volume
cjs.muted() // Get mute state
cjs.muted(true) // Mute
cjs.muted(false) // Unmute
cjs.subtitle(0) // Change active subtitle by indexcjs.on('available', () => {}) // Cast framework is ready
cjs.on('connect', () => {}) // Connected to a device
cjs.on('disconnect', () => {}) // Session ended
cjs.on('statechange', () => {}) // Player state changed
cjs.on('playing', () => {}) // Media is playing
cjs.on('pause', () => {}) // Media is paused
cjs.on('buffering', () => {}) // Buffering / seeking
cjs.on('end', () => {}) // Media ended
cjs.on('timeupdate', () => {}) // Current time changed
cjs.on('volumechange', () => {}) // Volume changed
cjs.on('mute', () => {}) // Muted
cjs.on('unmute', () => {}) // Unmuted
cjs.on('subtitlechange', () => {}) // Active subtitle changed
cjs.on('event', (e) => {}) // Catch all events except 'error'
cjs.on('error', (e) => {}) // Catch any errorscjs.available() // boolean β is Cast available
cjs.connected() // boolean β is connected to a device
cjs.device() // string β device name
cjs.state() // string β current state
cjs.paused() // boolean β is paused
cjs.src() // current media URL
cjs.title() // media title
cjs.description() // media description
cjs.poster() // poster image URL
cjs.subtitles() // array of subtitle tracks
cjs.progress() // progress (0 β 100)
cjs.volume() // volume (0 β 1)
cjs.muted() // is muted
cjs.time() // current time in seconds
cjs.time(true) // formatted time ("01:23")
cjs.duration() // duration in seconds
cjs.duration(true) // formatted durationcjs.cast('https://example.com/video.mp4', {
title: 'My Video',
description: 'Optional description',
poster: 'https://example.com/poster.jpg',
time: 30, // start position in seconds
paused: false,
subtitles: [{
label: 'English',
src: 'https://example.com/en.vtt',
subtype: 'SUBTITLES', // SUBTITLES | CAPTIONS | DESCRIPTIONS | CHAPTERS | METADATA
active: true
}],
// Optional (Netflix-style defaults are already applied)
subtitleStyle: {
backgroundColor: '#00000000',
foregroundColor: '#FFFFFF',
edgeType: 'DROP_SHADOW',
edgeColor: '#000000FF',
fontFamily: 'CASUAL',
fontScale: 1.0
}
});Question: Can I cast local resources?
Answer: It was possible in the past using service workers, but Google dropped support. See this issue.
Question: Do I need to enable CORS?
Answer: Yes. Chromecast is strict about CORS. You can allow the CrKey user-agent if you want to be more specific, but Access-Control-Allow-Origin: * is the simplest solution.
Do you want to support my work? Feel free to donate a β Hot Beverage
