requestAnimationFrame works on Chrome 22+, Edge 12+, Firefox 11+, Safari 6+, Opera 15+, and IE 10+. See per-browser support, throttling, and gotchas.

Prince Dewani
May 6, 2026
requestAnimationFrame is a WHATWG HTML Living Standard JavaScript method that schedules a callback to run right before the browser paints the next frame. It works unprefixed in Chrome 22+, Edge 12+, Firefox 11+, Safari 6+ on macOS and iOS, Opera 15+, Samsung Internet 4+, Android Browser 4.4+, and Internet Explorer 10+, while Opera Mini never added support.
This guide covers what requestAnimationFrame is, the browsers that support it, how it works under the hood, how it compares to setTimeout, the production use cases it powers, and the known issues you will hit when shipping animations across browsers.
requestAnimationFrame is a method on the WHATWG AnimationFrameProvider mixin, exposed on the global window. It accepts a callback and returns an integer ID. The browser invokes the callback once, just before the next paint, and passes a high-resolution timestamp to the callback so animations can scale by elapsed time.
requestAnimationFrame is supported unprefixed in every modern engine. Older Chrome and Firefox builds shipped vendor-prefixed variants, and Opera Mini still has no support at all.
Chrome supports requestAnimationFrame unprefixed from Chrome 22 on Windows, macOS, Linux, ChromeOS, and Android. Chrome 10 to 21 only exposed it as webkitRequestAnimationFrame, and Chrome 4 to 9 did not support it. Chrome for Android matches the desktop timeline from Chrome Android 25 on.
Edge supports requestAnimationFrame unprefixed from Edge 12 on Windows 10 and macOS. Chromium-based Edge 79 and later inherits the same engine timing as Chrome, so behaviour and high-refresh-rate handling match Chrome version for version.
Firefox supports requestAnimationFrame unprefixed from Firefox 11 on Windows, macOS, Linux, and Android. Firefox 4 to 10 shipped it as mozRequestAnimationFrame, and Firefox 2 to 3.6 did not support it. Firefox Android tracks the desktop timeline.
Safari supports requestAnimationFrame from Safari 6 on macOS and from Safari 6 on iOS and iPadOS. Safari 3.1 to 5.1 did not support it on either platform. Safari clamps the rate to the device refresh rate, including 120Hz on ProMotion iPhones and iPads.
Opera supports requestAnimationFrame from Opera 15 on Windows, macOS, and Linux, after the engine switch to Blink. Opera 9 to 12.1 did not support it. Opera Mini does not support requestAnimationFrame on any version because the proxy renderer skips per-frame JavaScript.
Samsung Internet supports requestAnimationFrame from Samsung Internet 4 on Android. Behaviour and throttling rules track the underlying Chromium build, so a Galaxy device on Samsung Internet 24 paints at the same cadence as Chrome Android 122.
The legacy Android Browser supports requestAnimationFrame from Android 4.4 onward, when WebView switched to the Chromium engine. Android 2.1 to 4.3 used the older WebKit-based WebView and did not support it.
Internet Explorer supports requestAnimationFrame from IE 10 on Windows 7 and later. IE 5.5 to 9 did not support it, so a setTimeout shim is required for any IE 9 fallback. Microsoft has retired Internet Explorer, so most teams can drop the shim now.
Note: requestAnimationFrame timing varies across Safari, Firefox, and Chrome on high-refresh-rate displays and throttled background tabs. Test it on real browsers and OS with TestMu AI. Try TestMu AI free!
requestAnimationFrame plugs into the browser's rendering loop. The engine batches your callback with style, layout, and paint so the work lands in the same frame the browser was about to render anyway.
Use the timestamp argument to scale motion by elapsed time. Without it, animations run twice as fast on a 120Hz ProMotion iPad as they do on a 60Hz monitor.
// Detect support and start a smooth, time-scaled animation.
if (typeof window.requestAnimationFrame === "function") {
const box = document.getElementById("box");
let firstFrame;
function step(now) {
if (firstFrame === undefined) firstFrame = now;
const elapsed = now - firstFrame;
// 0.2 px per millisecond, capped at 300 px so it stops cleanly.
const x = Math.min(elapsed * 0.2, 300);
box.style.transform = "translateX(" + x + "px)";
if (x < 300) requestAnimationFrame(step);
}
const rafId = requestAnimationFrame(step);
// Cancel before unloading the page so the queue stays clean.
window.addEventListener("beforeunload", () => cancelAnimationFrame(rafId));
} else {
console.log("requestAnimationFrame is not supported in this browser.");
}Both APIs schedule a callback, but only requestAnimationFrame is aware of the rendering pipeline. The table compares the dimensions that decide which one to reach for.
| Dimension | requestAnimationFrame | setTimeout |
|---|---|---|
| Timing source | Display refresh rate, synced with the next paint | Fixed millisecond delay you pass in |
| Frame alignment | Always runs once per frame, before style and layout | Fires whenever the timer expires, often mid-frame |
| Background tab behaviour | Paused when the tab is hidden or the iframe is offscreen | Throttled to about 1 call per second, but still runs |
| High refresh rate handling | Scales with 90Hz, 120Hz, and 144Hz displays automatically | Locked to the delay you set, so motion drifts on faster screens |
| Battery and CPU cost | Lower, because the browser skips the callback when no paint is needed | Higher, because the timer fires regardless of paint state |
| Best fit | Animations, canvas redraws, scroll-driven effects, game loops | Plain delays, retries, debounced one-shot work |
requestAnimationFrame is the default loop for any work that has to stay in step with the screen. The most common production patterns are below.
requestAnimationFrame is well supported, but the corner cases bite production code in predictable ways.
All requestAnimationFrame version numbers and platform notes in this guide come from these primary sources:
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance