Why a static button can time out in Playwright
Playwright's click stability check depends on animation frames, even when the target button is static.
I learned that a static button can time out in Playwright when the browser fails to deliver animation frames.
Note
Tested on Linux with Playwright 1.63.0 and Chromium Headless Shell 153.0.8010.12 on 2026-10-06.
Static buttons still need frames
Playwright automates browser tests. Before clicking, it checks that an element’s bounding box (position and size) stays unchanged across two consecutive animation frames (browser rendering updates). A static button still needs those updates to pass the check.
I isolated the timeout with a plain button page. Playwright found the element, but the click timed out waiting for it to become “stable.” A one-second probe received no animation frame.
GL refers to the OpenGL family of graphics interfaces, which programs use to draw images. Implementations can use graphics hardware or run in software on the main processor. Headless mode has no visible browser window; the browser still needs to render frames.
Bypassing GL startup on Linux
An existing launch workaround, --use-gl=disabled, restored frame delivery. In an existing Playwright setup, merge this setting into the configuration while preserving its other options and launch arguments:
// playwright.config.ts
import { defineConfig } from "@playwright/test";
export default defineConfig({
testDir: "./e2e",
use: {
launchOptions: {
args: process.platform === "linux" ? ["--use-gl=disabled"] : [],
},
},
});
Chromium’s GL startup source recognizes disabled and skips normal OpenGL initialization. That explains what the flag bypasses; the underlying graphics defect remains unidentified. The platform check leaves other platforms’ default launch behavior unchanged.
Verifying a normal click
I kept a five-second regression that supplies its own page, without needing an application server:
// e2e/browser-rendering.spec.ts
import { expect, test } from "@playwright/test";
test("clicks without a graphics-startup stall", async ({ page }) => {
await page.setContent(
`<button onclick="this.textContent = 'Clicked'">Ready</button>`,
);
await page.getByRole("button", { name: "Ready" }).click({ timeout: 5000 });
await expect(page.getByRole("button", { name: "Clicked" })).toBeVisible();
});
Run it with pnpm:
pnpm exec playwright test e2e/browser-rendering.spec.ts
The regression timed out before the flag and passed in 194 ms afterward, using the same click checks and deadline. All 25 tests in the browser suite then passed.
What this changes
Ordinary page interactions worked in this mode, but normal GL-backed rendering remained untested. WebGL (browser 3D graphics) and GPU (graphics processor) acceleration need coverage with the graphics backend they are meant to exercise. This is a workaround for the tested environment; Playwright warns that custom browser arguments can break functionality.
References
- Playwright actionability. The two-frame stability check.
- OpenGL specification, §1.2. Graphics interfaces and hardware/software implementations.
- Chromium headless documentation.
- Chromium GL initialization. The disabled implementation’s early returns.
- Playwright launch options.
- pnpm exec. Running the installed test command.
- Earlier Linux launch workaround.
This post was written with AI assistance.