Guide · Open source
How to use Tone.js: install, play sounds and schedule music in the browser
Updated · written with AI from the project's own documentation and checked against our catalogue data
Tone.js is a Web Audio framework for creating interactive music in web pages. It offers DAW-style features such as a global transport for scheduling events, plus prebuilt synths and effects. This guide shows you how to install it, play your first note, schedule repeating events and load audio samples, assuming you are comfortable with some JavaScript.
Quick start
- 1Install Tone.js. Run npm install tone in your project, or load Tone.js from unpkg.com in an HTML page before your own scripts.
- 2Import the library. Add import * as Tone from "tone"; at the top of your JavaScript file.
- 3Create and connect a source. Make a Tone.Synth and call toDestination() so its output reaches the speakers.
- 4Start audio on a user action. Attach a click listener to a button and call await Tone.start() inside it before playing anything.
- 5Trigger a note. Call triggerAttackRelease with a note, a duration such as "8n", and optionally a start time.
- 6Schedule a loop. Create a Tone.Loop, start it, then call Tone.getTransport().start() to play it in time.
How do you install Tone.js?
There are two ways to add Tone.js to a project. The first is to install it locally with npm. Node.js is only needed if you use npm. Install the latest stable version, or the next version if you want to try pre-release features.
You can also load Tone.js directly in an HTML document. It is hosted at unpkg.com and must come before any of your project scripts.
- Latest stable version: npm install tone
- Next version: npm install tone@next
- Import in JavaScript: import * as Tone from "tone";
npm install tone // Install the latest stable version
npm install tone@next // Or, alternatively, use the 'next' version
<script src="http://unpkg.com/tone"></script>How do you play your first sound?
Create a synth, connect it to the main output (your speakers), and trigger a note. Tone.Synth is a basic synthesizer with a single oscillator and an ADSR envelope.
triggerAttackRelease takes a note (a frequency in hertz or pitch-octave notation such as "D#2"), a duration (seconds or a tempo-relative value such as "8n"), and an optional start time.
//create a synth and connect it to the main output (your speakers)
const synth = new Tone.Synth().toDestination();
//play a middle 'C' for the duration of an 8th note
synth.triggerAttackRelease("C4", "8n");Why must you start audio from a user click?
Browsers will not play any audio until a user clicks something, such as a play button. Run your Tone.js code only after calling Tone.start() from an event listener triggered by a user action such as click or keydown.
Tone.start() returns a promise. Audio is ready only after that promise resolves. Scheduling or playing audio before the AudioContext is running results in silence or incorrect timing.
document.querySelector("button")?.addEventListener("click", async () => {
await Tone.start();
console.log("audio is ready");
});How do you schedule notes and loops with the Transport?
Tone tracks time with the AudioContext clock, which starts at 0 when the page loads and counts in seconds. Tone.now() returns the current value. You can also use note values such as "4n" (quarter note), "8t" (eighth-note triplet) and "1m" (one measure) anywhere a time is accepted.
Tone.getTransport() returns the main timekeeper. Unlike the AudioContext clock, it can be started, stopped, looped and adjusted on the fly. Tone.Loop is a simple way to create a looped callback. JavaScript callbacks are not precisely timed, so use the time value passed into the callback to schedule events.
- Tone.Loop runs a callback on a repeating interval
- Transport.start() starts all loops that were started at a given time
- Transport bpm can be changed while playing, for example with rampTo
const synthA = new Tone.FMSynth().toDestination();
const loopA = new Tone.Loop((time) => {
synthA.triggerAttackRelease("C2", "8n", time);
}, "4n").start(0);
Tone.getTransport().start();
Tone.getTransport().bpm.rampTo(800, 10);How do you play chords and load samples?
Tone's synths are monophonic, meaning they play one note at a time. To play several notes at once, wrap a monophonic synth in Tone.PolySynth, which handles note allocation. Tone.Sampler is polyphonic on its own and does not need PolySynth. It pitch shifts audio files to fill gaps between the notes you provide.
Tone.Player loads and plays back a single audio file. Use Tone.loaded() to wait until all audio files are loaded before playing.
- Tone.PolySynth(Tone.Synth) makes a polyphonic synth
- Tone.Sampler maps note names to files and fills in the gaps
- Tone.loaded() resolves when all audio files have loaded
const sampler = new Tone.Sampler({
urls: {
C4: "C4.mp3",
"D#4": "Ds4.mp3",
"F#4": "Fs4.mp3",
A4: "A4.mp3",
},
release: 1,
baseUrl: "https://tonejs.github.io/audio/salamander/",
}).toDestination();
Tone.loaded().then(() => {
sampler.triggerAttackRelease(["Eb4", "G4", "Bb4"], 4);
});How do you add effects?
By default, sources connect straight to the Destination. You can route a source through one or more effects before the speakers. Connections can run in series or in parallel, and several nodes can connect to the same input so sources share an effect. Tone.Gain is a utility node for building more complex routing.
- Serial: connect a player to a distortion, then to the destination
- Parallel: connect one player to both a filter and a feedback delay
const distortion = new Tone.Distortion(0.4).toDestination();
player.connect(distortion);What people use it for
- Adding interactive sound effects or a playable instrument to a web page
- Prototyping synth sounds and sequences in the browser
- Learning how Web Audio scheduling works through readable examples
- Building browser-based music toys or generative music experiments
- Playing sample-based instruments built from audio files organised by note
Frequently asked questions
Is Tone.js free to use?
Tone.js is released under the MIT licence. Check the repository's license file for the full terms before using it in your project.
What do I need to install Tone.js?
You need Node.js only if you install through npm. You can also add Tone.js to a page with a script tag that loads it from unpkg.com, placed before your project scripts.
Why is there no sound when I run my Tone.js code?
Browsers block audio until the user interacts with the page. Call await Tone.start() from a click or keydown handler, and do not schedule audio before that promise resolves.
Can I use Tone.js without knowing JavaScript?
Tone.js is a code library, and its examples assume familiarity with JavaScript. Complete beginners will face a steeper learning curve and may want to learn basic JavaScript first.
How is Tone.js different from the Web Audio API?
Tone.js is built on the Web Audio API and adds higher-level features such as a transport, prebuilt synths and effects, and musical time notation. The Web Audio API is the native browser layer that Tone.js uses.
Can Tone.js run outside the browser?
No. The README describes Tone.js as a Web Audio framework for the browser, so it is not suited to audio processing outside the browser.
New agent skills, repos and AI tools — every week
The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.
Our verdict
Tone.js suits developers adding interactive sound to web pages, and musicians or students who want to prototype synths and sequences in the browser. It is not a good fit if you want a standalone desktop music app, need audio processing outside the browser, or have no JavaScript experience.
Install options & downloads