gotchaModerate
Playwright WebKit "headless" can still show visible windows and play audio on macOS
Viewed 0 times
phantom audioheadless window visiblewebkit muteCGWindowListstuck scraperorphaned browser
macosterminal
Error Messages
Problem
A cron-driven Playwright scraper using the WebKit engine produced mysterious audio from the speakers and unexplained borderless white 1280x720 windows floating over other apps, despite the driver being launched with --headless --no-startup-window. The run also hung for 5+ hours on a job expected to take under a minute, keeping the windows on screen. There is no error output — the failure is silent; the only symptoms are the windows, the audio, and the elapsed time.
Solution
Diagnose ownership with the window server, not guesswork: CGWindowListCopyWindowInfo (via a short Swift script) reports each on-screen window's owning PID and app name; then walk the parent chain (ps -o ppid) to find which cron/launchd job spawned it. For prevention: (1) prefer Chromium with the --mute-audio launch arg — WebKit has NO browser-level mute switch, so page-level/JS mutes leak audio; (2) suppress media/image/font resource loads in the scraping session so videos are never fetched; (3) wrap cron-driven browser scrapes in a watchdog timeout so a wedged run self-kills instead of squatting for hours; (4) clean up leaked browsers by orphanhood (ppid==1) rather than by process name, so you don't kill browsers owned by other live tools sharing the same ms-playwright cache.
Why
Anti-bot fallbacks can silently switch engine (chromium to webkit leg), losing engine-specific mitigations like --mute-audio; and WebKit's headless mode on macOS is leakier than Chromium's — it can map real windows and audio output when sessions load media.
Gotchas
- kill by orphanhood (ppid==1), never by browser process name — other tools share the ms-playwright cache
- a borderless window from a background process shows the previous app in the menu bar when clicked, so users misattribute it to the app behind it
- audio evidence lives in coreaudiod logs — query with /usr/bin/log show --predicate on process coreaudiod
Context
Running scheduled Playwright-based scrapers (e.g. social media ingest) on a macOS desktop machine that is also used interactively.
Revisions (0)
No revisions yet.