Skip to main content
React renders the Bunny Player iframe like any other element. The BunnyPlayer component below adds player.js, forwards the player’s events as props, and hands you a Player for controlling playback. It assumes a client-rendered app, such as one built with Vite. For server rendering, including Remix and React Router framework mode, follow the Next.js guide.

React example on GitHub

A Vite app with custom controls and an event log.

Quickstart

1

Install player.js

player.js ships without types. Add a declaration file anywhere your tsconfig.json includes, for example player.js.d.ts. It covers the methods and events the Bunny Player supports:
player.js.d.ts
2

Create the component

The Player is created once the iframe is in the DOM. Callbacks live in a ref, which stops inline props from re-creating the player on every render.
components/bunny-player.tsx
3

Render a video

The library ID and video GUID are on the video’s page in the dashboard.
params takes any player parameter, such as captions, t, or muted.

Control playback

onReady hands you the Player. Keep it in state for your own controls.
Getters answer through a callback, since the value comes back from the iframe.
Playback speed is missing from the npm build (0.1.0), and send() covers the gap. The build we host adds setPlaybackRate(), getPlaybackRate() and playbackratechange (Methods).
Browsers block unmuted play() before the viewer has clicked anything. Call player.mute() first if playback has to start on its own. The Playback control API lists every method and event.

Track progress

timeupdate fires several times a second. Throttle it before it reaches your backend.
Pass the saved position back as params={{ t: savedSeconds }} to resume.

Load player.js from the CDN instead

To drop the npm dependency, load our hosted build from the component.
lib/load-playerjs.ts
Hold playerjs in state, set it from loadPlayerjs() in an effect, and render a placeholder until it loads, as the Next.js component does.

Troubleshooting

player.js has to be loaded before the iframe finishes loading. It caches the iframe’s ready message on import, and a Player created later still connects. In a client-rendered app, importing it with the component is early enough. Server-rendered HTML can load the iframe before your JavaScript runs, which the Next.js guide handles.A hidden tab also holds ready back until the viewer switches to it.
The library’s allowed domains, direct access block, or token authentication is rejecting the embed. See Embedding restrictions.
Last modified on October 7, 2026