This Month in Ladybird - May 2026 Ladybird, an open-source web browser, now clears Cloudflare Turnstile bot detection and has moved scrolling to an out-of-process compositor for smoother performance. The project also enabled Media Source Extensions by default, improving video streaming support including adaptive streaming on YouTube. These updates were part of 464 pull requests merged in May 2026, funded by sponsors including CodeRabbit and wheelofnames.com. Hello friends May was a busy month, with 464 pull requests merged. Ladybird now clears Cloudflare Turnstile, and scrolling has moved onto an out-of-process compositor. Here’s what we’ve been up to. Welcoming new sponsors Ladybird is entirely funded by the generous support of companies and individuals who believe in the open web. This month, we’re excited to welcome the following new sponsors: - CodeRabbit https://coderabbit.ai with $10,000 - wheelofnames.com https://wheelofnames.com with $1,000 We’re incredibly grateful for their support. If you’re interested in sponsoring the project, please contact us mailto:contact@ladybird.org . Passing Cloudflare Turnstile Cloudflare Turnstile https://www.cloudflare.com/products/turnstile/ is the bot-detection challenge that sits in front of a large number of sites, deciding whether you’re a real browser before it lets you reach the page. Until this month it refused to let Ladybird through, which kept us out of a lot of sites. Two things got us here. Over the past several months we’ve been chipping away at the many little web compatibility gaps that Cloudflare’s checks expect a real browser to handle. Cloudflare also made a change on their end to help. We can’t say exactly which combination of the two did it, but in our testing Ladybird now clears the challenge and loads the page. Async scrolling on an out-of-process compositor Scrolling has historically run on the main thread, so a busy page could make scrolling stutter. Scrolling now runs asynchronously on the compositor, covering viewport scrolling 9370 https://github.com/LadybirdBrowser/ladybird/pull/9370 , nested scrollable boxes 9407 https://github.com/LadybirdBrowser/ladybird/pull/9407 , and viewport scrollbars 9386 https://github.com/LadybirdBrowser/ladybird/pull/9386 . It’s enabled by default 9413 https://github.com/LadybirdBrowser/ladybird/pull/9413 . The compositor also runs in its own process now 9564 https://github.com/LadybirdBrowser/ladybird/pull/9564 , with backing store management moved across the boundary and crash recovery so a compositor crash doesn’t take down the page 9589 https://github.com/LadybirdBrowser/ladybird/pull/9589 . It’s the default compositor backend 9604 https://github.com/LadybirdBrowser/ladybird/pull/9604 . Scrolling stays smooth even while the main thread is busy with layout or JavaScript. Here’s IMDb being scrolled while it loads, without and with async scrolling: | Without async scrolling | With async scrolling | |---|---| Media Source Extensions on by default Media Source Extensions https://developer.mozilla.org/en-US/docs/Web/API/Media Source Extensions API is now on by default after a month behind an experimental flag 9673 https://github.com/LadybirdBrowser/ladybird/pull/9673 . MSE is how streaming sites feed media to the player in chunks, so turning it on lets a lot more video sites work, and unlocks adaptive streaming on YouTube: higher resolutions, higher frame rates, and quality switching. The same PR added SourceBuffer capacity limits, so Ladybird evicts buffered media data instead of holding onto it indefinitely. Under the hood, LibMedia’s pipeline was rewritten to allow media data processing to be inserted easily, and seeks are now handled as part of that flow instead of being tracked separately 9288 https://github.com/LadybirdBrowser/ladybird/pull/9288 . Forward video seeks are now aware of already-decoded data in the pipeline, making forward frame skipping on YouTube instant 9495 https://github.com/LadybirdBrowser/ladybird/pull/9495 . The built-in media controls now display buffered ranges, which are accurately reported for MP3, FLAC, Ogg, WAV, Matroska, and MP4 9705 https://github.com/LadybirdBrowser/ladybird/pull/9705 . HTMLMediaElement.getStartDate https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/getStartDate is implemented 9218 https://github.com/LadybirdBrowser/ladybird/pull/9218 . On-disk JavaScript bytecode cache JavaScript bytecode is now cached on disk 9259 https://github.com/LadybirdBrowser/ladybird/pull/9259 . RequestServer stores bytecode cache blobs as sidecar data alongside script HTTP disk cache entries, and warm cache hits can map bytecode from disk instead of keeping it in anonymous heap memory. On large modern websites, that saves hundreds of megabytes while also avoiding recompilation. The mapped cache is lazily decoded, so warm hits only pay to decode functions, source text, and instruction streams as they’re actually used 9433 https://github.com/LadybirdBrowser/ladybird/pull/9433 , 9453 https://github.com/LadybirdBrowser/ladybird/pull/9453 , 9466 https://github.com/LadybirdBrowser/ladybird/pull/9466 , 9472 https://github.com/LadybirdBrowser/ladybird/pull/9472 , 9486 https://github.com/LadybirdBrowser/ladybird/pull/9486 , 9540 https://github.com/LadybirdBrowser/ladybird/pull/9540 . A WebAssembly JIT LibWasm gained a Cranelift https://cranelift.dev/ -based just-in-time compiler 8866 https://github.com/LadybirdBrowser/ladybird/pull/8866 . Instead of interpreting WebAssembly bytecode, hot modules are compiled to native code. That shows up in benchmarks: roughly 8x on CoreMark, and 3-4x on function-call microbenchmarks. The JIT supports macOS 9356 https://github.com/LadybirdBrowser/ladybird/pull/9356 and is enabled by default 9758 https://github.com/LadybirdBrowser/ladybird/pull/9758 . Content blocking We rebuilt Ladybird’s content blocker. The old one was a simple URL substring matcher; the new one is backed by brave/adblock-rust https://github.com/brave/adblock-rust , Brave’s mature open-source content-filtering library 9538 https://github.com/LadybirdBrowser/ladybird/pull/9538 , 9587 https://github.com/LadybirdBrowser/ladybird/pull/9587 . It reads standard Adblock Plus / EasyList-style filter lists, and beyond network request filtering it now does cosmetic filtering, hiding page elements with CSS, including generic class and id selectors gathered from shadow-including descendants. Block lists are configurable and can be loaded from settings 9601 https://github.com/LadybirdBrowser/ladybird/pull/9601 . The HTML parser is now written in Rust Continuing our push to handle untrusted data from the web in memory-safe languages, the HTML parser fully migrated to Rust this month. The tokenizer 9429 https://github.com/LadybirdBrowser/ladybird/pull/9429 , tree-construction parser 9457 https://github.com/LadybirdBrowser/ladybird/pull/9457 , and speculative preload scanner 9462 https://github.com/LadybirdBrowser/ladybird/pull/9462 are now all Rust. The Rust parser is also about 10% faster than the C++ version it replaced, and was checked against a corpus of around 7,000 websites for DOM parity with the old parser. The URL parser and URLPattern implementation moved to Rust as well 9460 https://github.com/LadybirdBrowser/ladybird/pull/9460 . Incremental GC sweeping The GC now sweeps incrementally instead of doing all the work in one stop-the-world pass 7663 https://github.com/LadybirdBrowser/ladybird/pull/7663 . Long sweeps are cut into small slices, one heap block at a time, interleaved with normal program execution and driven by both a background timer and allocation pressure. That means fewer long pauses you can actually feel while browsing. Supporting changes make that pacing work better: heap blocks now come from 2 MiB chunks with decommit deferred to a worker thread 9299 https://github.com/LadybirdBrowser/ladybird/pull/9299 , the collector runs when JavaScript execution goes idle 9423 https://github.com/LadybirdBrowser/ladybird/pull/9423 , and thresholds account for memory held outside the GC heap 9286 https://github.com/LadybirdBrowser/ladybird/pull/9286 . A new family of GC-aware container types also landed, fixing long-standing bugs from keeping GC objects in plain containers 9494 https://github.com/LadybirdBrowser/ladybird/pull/9494 , 9650 https://github.com/LadybirdBrowser/ladybird/pull/9650 , 9694 https://github.com/LadybirdBrowser/ladybird/pull/9694 . CSS features - : Container queries now work, with thequeries @container container / container-name properties parsed and propagated 9298 https://github.com/LadybirdBrowser/ladybird/pull/9298 , name-only queries 9319 https://github.com/LadybirdBrowser/ladybird/pull/9319 , and size queries 9405 https://github.com/LadybirdBrowser/ladybird/pull/9405 . - : We implemented @scope @scope , including implicit element scope 9534 https://github.com/LadybirdBrowser/ladybird/pull/9534 , 9677 https://github.com/LadybirdBrowser/ladybird/pull/9677 , and made @supports at-rule @foo work so pages can feature-detect it 9536 https://github.com/LadybirdBrowser/ladybird/pull/9536 . - : Initial CSS grid subgrid support landed Subgrid https://developer.mozilla.org/en-US/docs/Web/CSS/CSS grid layout/Subgrid 9620 https://github.com/LadybirdBrowser/ladybird/pull/9620 , 9628 https://github.com/LadybirdBrowser/ladybird/pull/9628 . - Transitions and animations on all pseudo-elements : CSS transitions and animations now apply to every pseudo-element, not just a handful 9519 https://github.com/LadybirdBrowser/ladybird/pull/9519 . - Scroll APIs :is implemented for boxes scrollIntoView 9225 https://github.com/LadybirdBrowser/ladybird/pull/9225 , and we addedand scroll-margin scroll-padding 9367 https://github.com/LadybirdBrowser/ladybird/pull/9367 . - : First-letter pseudo-element styles are now applied ::first-letter 8885 https://github.com/LadybirdBrowser/ladybird/pull/8885 . - Gradient fixes : Conic gradients are now painted with Skia’s sweep shader 9665 https://github.com/LadybirdBrowser/ladybird/pull/9665 , -webkit-linear-gradient numeric angles are converted correctly 9528 https://github.com/LadybirdBrowser/ladybird/pull/9528 , and gradient color stops interpolate using premultiplied alpha 9765 https://github.com/LadybirdBrowser/ladybird/pull/9765 . DevTools layout inspection The DevTools inspector can now inspect grid layouts, showing line numbers, named areas, infinitely-extended lines, recoloring, and subgrid hierarchies 9672 https://github.com/LadybirdBrowser/ladybird/pull/9672 : Flexbox inspection landed too 9707 https://github.com/LadybirdBrowser/ladybird/pull/9707 : There’s now a “pick element” button that lets you click an element in the page to select it in the inspector 9735 https://github.com/LadybirdBrowser/ladybird/pull/9735 , implemented for the Qt and AppKit frontends. DevTools can also drive page navigation now 9801 https://github.com/LadybirdBrowser/ladybird/pull/9801 . Browser UI Tabs can now run down the side of the window instead of across the top, in the Qt frontend 9795 https://github.com/LadybirdBrowser/ladybird/pull/9795 , 9797 https://github.com/LadybirdBrowser/ladybird/pull/9797 . Switch them on and the sidebar shows each tab’s favicon and title, the window controls fold into the navigation toolbar, and the separate titlebar row disappears. It works in both light and dark themes, and you can collapse the sidebar when you want the space. The Qt chrome was refreshed as well 9631 https://github.com/LadybirdBrowser/ladybird/pull/9631 , 9788 https://github.com/LadybirdBrowser/ladybird/pull/9788 . The stock Qt look is replaced with an integrated custom chrome surface for the tab strip, toolbar, omnibox, and window controls, using a quieter, more neutral palette in both themes and generated chrome icons in place of the old TinyVG assets. The omnibox shows a shortened URL while you’re not editing, with contextual leading indicators a “Not secure” pill for HTTP, a globe for URL-like typed input, a search icon for search input . Tabs support browser-like dragging reorder, detach, and reparent between windows , frameless windows show resize cursors, and theme changes refresh the whole chrome immediately. This is still early UI iteration, not a final design, but the Qt frontend is starting to feel much more browser-shaped. Other UI improvements this month: - Page loading state is now shown in the browser chrome, so you can tell a page is loading 9500 https://github.com/LadybirdBrowser/ladybird/pull/9500 - Reopen recently closed tabs and windows 9284 https://github.com/LadybirdBrowser/ladybird/pull/9284 - Detach a dragged tab into a new window by dropping it outside any tab bar 9636 https://github.com/LadybirdBrowser/ladybird/pull/9636 - Zoom level is persisted and restored per host 9255 https://github.com/LadybirdBrowser/ladybird/pull/9255 , with a zoom indicator in the location bar 9790 https://github.com/LadybirdBrowser/ladybird/pull/9790 - Middle-mouse primary paste, integrated with the X11 selection clipboard 9421 https://github.com/LadybirdBrowser/ladybird/pull/9421 , 9686 https://github.com/LadybirdBrowser/ladybird/pull/9686 - Sharper icons on high-DPI displays 9698 https://github.com/LadybirdBrowser/ladybird/pull/9698 Networking and privacy - : HTTP Strict Transport Security is now implemented, so sites that send the header are upgraded to HTTPS on subsequent visits HSTS https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security 9475 https://github.com/LadybirdBrowser/ladybird/pull/9475 . - : We added the Permissions API along with the geolocation permission Permissions API https://developer.mozilla.org/en-US/docs/Web/API/Permissions API and geolocation 8874 https://github.com/LadybirdBrowser/ladybird/pull/8874 . - Encoding detection : A-based detector now guesses the character encoding of pages that don’t declare one chardetng 9375 https://github.com/LadybirdBrowser/ladybird/pull/9375 . Sites that work better TradingView https://www.tradingview.com charts render now. Implementing lets the site get past its startup feature checks, and a canvas compositing fix stops translucent chart pixels from accumulating as you move the mouse https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/getRegistrations ServiceWorkerContainer.getRegistrations 9581 https://github.com/LadybirdBrowser/ladybird/pull/9581 . | Before | After | |---|---| Discord https://discord.com got several rendering and interaction fixes 9764 https://github.com/LadybirdBrowser/ladybird/pull/9764 . foreignObject descendants now participate in hit testing, CSS mask image layers and avatars paint correctly, and drag-selection in the chat layout is much more forgiving, so a selection can start from gutters, avatar-adjacent areas, author names, and the space below message text instead of silently doing nothing. Shopify https://www.shopify.com no longer crashes on same-document navigation 9391 https://github.com/LadybirdBrowser/ladybird/pull/9391 . Preserving imported binding names in the module bytecode cache removes visible jank during Shopify’s hydration, and grid sizing fixes clear up spurious horizontal scrolling on both Shopify and . https://reddit.com Reddit Hacker News https://news.ycombinator.com threads got lighter 9753 https://github.com/LadybirdBrowser/ladybird/pull/9753 . Large pages full of nested tables and inline text were doing a lot of avoidable work in the style and layout hot paths. Simple tables now skip redundant row intrinsic sizing, inline layout reuses cached text chunk lists instead of copying them, and scoped rule matching reuses its scratch storage between elements. A few more: - : The new Skia-backed conic gradient painting cleans up the rendering of the wheel edge wheelofnames.com 9665 https://github.com/LadybirdBrowser/ladybird/pull/9665 . - blt.se : Fixed unwanted horizontal and vertical scrolling in the top navigation bar, caused by async wheel hit testing treating hidden overflow axes as scrollable 9455 https://github.com/LadybirdBrowser/ladybird/pull/9455 . Web Platform Tests WPT Our WPT https://web-platform-tests.org score went from 2,067,263 to 2,075,546 this month, a gain of 8,283 subtests. Other notable changes - Themed text selection colors : Selection highlights now use the system theme’s colors 9704 https://github.com/LadybirdBrowser/ladybird/pull/9704 . - No more white flash : Dark-mode pages no longer flash white while loading 9690 https://github.com/LadybirdBrowser/ladybird/pull/9690 . - Animated images pause in inactive tabs , saving CPU on background tabs 9675 https://github.com/LadybirdBrowser/ladybird/pull/9675 . - Largest favicon wins : We now select the largest decoded favicon as the active page favicon 9713 https://github.com/LadybirdBrowser/ladybird/pull/9713 . That’s it for May. Thanks for reading, and we’ll see you next month.