The web platform is way more powerful than most developers realize — and every year it quietly gains new superpowers.
Sometimes choosing a topic is harder than writing the article itself.
When I thought about what to write this week, only two types of ideas kept comming to mind:
either potential bangers, or deep technical dives.😅 But I wanted something lighter. Still technical, still useful. But not a 3-day research rabbit hole.
And since I genuinely love exploring what the browser can do (and how far we can push it), I landed on a sneaky topic: underused Web APIs.
Some of these might be daily bread for you.
But I’m pretty sure at least a few will make someone go “wait, this exists?!” 😉
And if you enjoy edge-tech topics and happen to be in Italy this April — come to jsday.it, where I’ll be speaking about WebGPU + WASM 🙂
Alright, enough intro. Let’s start.
Here are 10 browser APIs that deserve way more love.
1) Structured Clone API
I have a love–hate relationship with this one.
For years, one of my favorite interview questions to ask candidates was:
“How do you copy an object?”
You could learn so much from the answer:
- Do they understand references?
- Do they know
Object.assign, spread, JSON tricks? - Do they mention libraries?
- Do they panic? 😄
Now?
const copy = structuredClone(original);
Boom. Perfect deep copy.
Part of me is happy.
Part of me misses that interview question already.
Nice extras
- Works with
Map,Set,Date,Blob,File,ArrayBuffer - Handles circular references (no more JSON stringify explosions 💥)
- Does NOT clone functions
Support: Modern browsers (Chrome, Firefox, Safari, Edge). Safe for production.
2) Performance API
Very underrated.
We talk a lot about performance. We install tools. We run Lighthouse. We debate optimizations.
But sometimes you just want to check:
“Is A actually faster than B, or am I overengineering?”
performance.mark("start");
// code to measure
performance.mark("end");
performance.measure("calc", "start", "end");
console.log(performance.getEntriesByName("calc"));
Perfect for:
- micro-benchmarks
- checking if a Worker or WASM is worth it
- reality-checking your assumptions
Because sometimes the “optimized” version is slower 😅
Support: Excellent across all modern browsers.
3) Page Visibility API
Detects whether the tab is active.
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
video.pause();
}
});
Real talk:
Users will open your app, then switch tabs for 20 minutes.
Or 2 hours.
Or forever.
Use cases:
- pause videos
- stop polling
- reduce CPU usage
- cleaner analytics
Your backend (and battery life) will thank you.
Support: All modern browsers.
4) ResizeObserver
Finally — observing element size, not just window size.
const ro = new ResizeObserver(entries => {
for (const entry of entries) {
console.log(entry.contentRect.width);
}
});
ro.observe(element);
If you ever built responsive components, charts, or dashboards, you probably wrote some cursed resize logic in the past.
This API feels like the browser saying:
“Relax, I got you now.”
Support: Modern browsers, widely available.
5) IntersectionObserver
The sibling of ResizeObserver.
Checks if an element is in the viewport.
const io = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log("Visible!");
}
});
});
io.observe(element);
Amazing for:
- infinite scroll
- lazy loading
- scroll animations
Anyone who implemented infinite scroll manually once…
never wants to do it again 😄
Support: All modern browsers.
6) AbortController
Many devs know it for fetch…
But it can cancel more than just fetch.
const controller = new AbortController();
fetch(url, { signal: controller.signal });
// later
controller.abort();
You can also use it for:
- event listeners
- streams
- any abortable API
Even better:
👉 One signal can cancel multiple operations.
Clean, scalable, and very “grown-up codebase” friendly.
Support: All modern browsers.
7) Idle Detection API
Page Visibility tells you if the tab is active.
Idle Detection tells you if the human is active.
const detector = new IdleDetector();
await detector.start();
detector.addEventListener("change", () => {
console.log(detector.userState);
});
Meaning:
User might have your app open…
but is actually making coffee ☕ or in a meeting.
Use cases:
- auto-logout
- “away” status
- background optimizations
Yes, you can detect if the user left the computer.
A bit creepy. Very useful 😄
Support: Mostly Chromium-based. Requires permission.
8) BroadcastChannel API
Easy multi-tab communication.
const channel = new BroadcastChannel("app");
channel.postMessage("logout");
channel.onmessage = e => {
console.log(e.data);
};
Great for:
- logout sync
- auth state
- shared session logic
Surprisingly practical in real apps where users open 5 tabs “just in case.”
Support: Modern browsers. Safari joined later but supports it.
9) Web Locks API
The cousin of BroadcastChannel.
Prevents duplicate work across tabs.
navigator.locks.request("data-lock", async lock => {
await fetchData();
});
Example:
- only one tab fetches notifications
- avoids backend spam
- coordinates shared resources
Feels very “distributed systems meets frontend.”
Support: Mostly Chromium. Not universal.
10) File System Access API
Yes — real filesystem access from the browser.
const [fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
Great for:
- web editors
- import/export tools
- power-user apps
The first time you use it, it feels slightly illegal.
Like “are we really allowed to do this on the web?” 😄
Support: Chromium-heavy. Limited elsewhere.
Reality Check 🧠
Many of these APIs are well supported in modern browsers.
But some (Idle Detection, File System Access, Web Locks) are still Chromium-centric.
So always check compatibility before going all-in.
But simply knowing these exist?
That already gives you an edge.
The web platform evolves fast.
Sometimes the “new tech” isn’t a framework — it’s a native browser feature that’s been sitting there quietly.
What’s your favorite underrated Web API that nobody talks about?
Top comments (58)
You captured it perfectly. It really comes down to your mental model. When you're writing a UI in React, it helps to remember that your code ultimately runs in a platform‑specific environment, the browser. That means at least two engines are involved in interpreting your work: V8 for JavaScript (ECMAScript) and, for example, Blink for DOM operations, rendering, and the browser APIs you mentioned.
React is simply a tool that embraces a compositional approach, helping developers build UI components quickly and consistently. But it’s completely valid to interact directly with browser APIs or even the DOM itself when needed. React may call it an anti‑pattern, but it still gives you the escape hatches, like useRef to do it when the situation calls for it.
And here’s the fun part: I spent several years at Facebook working closely with the React team, not as a member of the team, but as a microservices systems engineer. Even there, it was understood that sometimes writing an “anti‑pattern” is the pragmatic choice.
Exactly 🙂 Those APIs exist for a reason - to be used when they make sense. Frameworks are great abstractions, but the browser is still the actual runtime and it’s good to stay aware of that layer.
And honestly, I wouldn’t call useRef some huge anti-pattern either - it’s more like an escape hatch for when you really need to interact with the platform directly. Used thoughtfully, it’s just pragmatic engineering.
I mostly work in Angular day to day, but the idea is the same there: sometimes going a bit closer to the platform is simply the right tool for the job 🙂
Even if you write React code, so many times happen need to reach that browser API in a useEffect.
Great list 👌
Honestly, APIs like
ResizeObserver,IntersectionObserver, andAbortControllerreplaced so many small libraries in my projects without me realizing it. The browser already solves problems we often reach for npm packages for.Posts like this are a good reminder to check “can the platform do this?” before installing another dependency.
Oh yes - thanks for this comment! That’s exactly the point I was hoping to highlight 🙂 The platform has grown so much that it often solves problems we used to reach for libraries for by default. Sometimes it’s just about pausing and asking “can the browser already do this?” before adding another dependency.
Congratulations!
For speaking and for your post: browser APIs are useful and powerful, but often underrated. Your post is a great reminder, I'll keep it handy…
Thanks, Pascal! 🙂 And yes - especially in the era of a million frontend libraries, native APIs are such a great option. Honestly, I might write something about frontend node_modules one day too… that whole ecosystem can be quite a circus 😄
One thing I have noticed after working on AI heavy and security sensitive products is that native browser APIs age far better than most helper libraries. Dependencies tend to multiply risk over time. Audits, updates, breaking changes, abandoned maintainers. Meanwhile browser APIs evolve more conservatively and with long term stability in mind.
In AI powered applications this becomes even more important. When your bundle already includes large runtimes like LLM, WASM, or media processing, every extra dependency has a real cost. Not only in size, but also in trust, review time, and operational complexity.
Treating the browser as a first class platform, not just a host for frameworks, leads to cleaner mental models and better architectural decisions. Frameworks like React are great productivity tools, but knowing when to lean on the platform directly is a senior level skill.
This post is a great reminder that sometimes the most modern choice is also the most boring one. And that is usually a very good sign.
Exactly this 🙂 And that’s not even touching how those dependencies often look in practice - layers of peer-dependencies (sometimes for the most trivial things), and then explaining every single one in security reports, including packages you didn’t even knowingly install.
The longer I work in this field, the more I’m convinced it’s worth thinking three times before adding a utility library - especially for UI concerns that the platform can often handle already. Fewer dependencies usually means fewer surprises later.
Good reminder: don’t reach for a library before checking native browser APIs. Modern web has built-in solutions for many common needs - using them keeps bundles smaller, performance higher, and complexity lower.
ABSOLUTELY - I couldn’t agree more, and the longer I work in this field, the more I feel it. Especially when you go through security audits that scrutinize every package and dependency 😄 Suddenly that “tiny helper library” doesn’t feel so tiny anymore.
For the people that like reading documentation:
Thanks for sharing the links! And absolutely - if any of these APIs spark someone’s interest, diving into the documentation is the best next step 🙂
Thanks for putting this list together! There are so many useful Browser APIs that we don't use on a daily basis, it’s great to to refresh that knowledge. Infinite scroll without IntersectionObserver though, not even sure how to approach that 😅
Haha, it really was a nightmare 😄 I still remember implementing it in early Angular days - even with a library it was a painful journey. IntersectionObserver was a lifesaver when it arrived.
About the ResizeObserver,
I have tried it out in the past, created a handler for it and had it working too but then I came across the *'window.visualViewport' together with its 'resize' listener.
A long story short, I abandoned that handler and switched to that straight away.
Thanks for sharing! It’s always great to hear real “from the trenches” experiences 🙂
I’d say though that it’s not exactly the same thing - visualViewport and ResizeObserver solve slightly different problems. One is more viewport-level, the other is element-level, so it really depends on the use case.
Ah! Here we go again: developer.mozilla.org/en-US/docs/W...
Ah, I know what you mean - sounds like you’d enjoy a follow-up post 😄
This is a great reminder.
The web platform is more powerful than most devs realize.
Fewer dependencies also means fewer surprises long-term.
Oh yes, absolutely! The more dependencies you add, the bigger circus they become to maintain later 😄