Technical research on macOS window privacy APIs, screen capture exclusion, and window server internals.
This repository documents the macOS window server APIs that control window visibility in screen captures, recordings, and window enumeration. These APIs are used by macOS itself for system UI elements (e.g., the screenshot selection overlay, Notification Center) and are accessible to third-party applications.
CGWindowListCopyWindowInfo is the primary API for discovering on-screen windows:
CFArrayRef windowList = CGWindowListCopyWindowInfo(
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
kCGNullWindowID
);Returns an array of dictionaries containing:
kCGWindowNumber- unique window IDkCGWindowOwnerPID- process ID of the owning applicationkCGWindowOwnerName- process namekCGWindowBounds- position and sizekCGWindowLayer- window level (normal, floating, status bar, etc.)kCGWindowSharingState- capture/sharing permissionskCGWindowName- window title (requires accessibility permissions)
The sharing state determines whether a window appears in screen captures:
| State | Value | CGWindowList | Screen Capture | Screen Recording |
|---|---|---|---|---|
kCGWindowSharingNone |
0 | Excluded | Excluded | Excluded |
kCGWindowSharingReadOnly |
1 | Included | Excluded | Excluded |
kCGWindowSharingReadWrite |
2 | Included | Included | Included |
Private API to set a window's sharing state:
extern CGError CGSSetWindowSharingState(
CGSConnectionID cid,
CGSWindowID wid,
CGSSharingState state
);Where CGSSharingState:
0= None (fully private)1= Read only2= Read/Write (default)
extern CGSConnectionID CGSMainConnectionID(void);
// or
extern CGSConnectionID _CGSDefaultConnection(void);extern CGError CGSSetWindowLevel(
CGSConnectionID cid,
CGSWindowID wid,
CGWindowLevel level
);Common levels:
kCGNormalWindowLevel(0) - standard windowskCGFloatingWindowLevel(3) - floating panelskCGStatusWindowLevel(25) - status bar levelkCGScreenSaverWindowLevel(1000) - above everything
Modern framework for screen capture that respects sharing states:
let filter = SCContentFilter(
display: display,
excludingWindows: [privateWindow]
)
let stream = SCStream(filter: filter, configuration: config, delegate: delegate)Windows with sharingType = .none are automatically excluded from all SCStream output, SCScreenshotManager captures, and SCRecordingOutput.
The public AppKit API for setting sharing type:
window.sharingType = .none // Excluded from capture
window.sharingType = .readOnly // Visible but not capturable
window.sharingType = .readWrite // Default - fully visibleImportant: Setting sharingType on an NSWindow calls through to CGSSetWindowSharingState internally. However, AppKit may reset this value during certain window operations (e.g., makeKeyAndOrderFront).
To ensure a window stays excluded from screen capture:
- Set
sharingType = .noneafter window creation - Use
orderFrontRegardless()instead ofmakeKeyAndOrderFront(_:)to avoid AppKit resetting the sharing type - Re-apply
sharingType = .noneafter any operation that might reset it
Python script to check if a window appears in CGWindowList:
import Quartz
options = Quartz.kCGWindowListOptionOnScreenOnly
windows = Quartz.CGWindowListCopyWindowInfo(options, Quartz.kCGNullWindowID)
for w in windows:
print(f"{w.get('kCGWindowOwnerName', '?')}: {w.get('kCGWindowName', '?')} (sharing={w.get('kCGWindowSharingState', '?')})")screencapture -x /tmp/test.png
# Windows with sharingType .none will not appearThis research is used in LDBypass, a macOS application that renders AI assistants (ChatGPT, Claude) in a private overlay window that is invisible to proctoring software. The overlay uses sharingType = .none at the window server level to remain excluded from all screen capture and window enumeration.
- Proctoring Compatibility Matrix
- macOS Screen Privacy Guide
- LDBypass Website
- Discord Community
- Apple ScreenCaptureKit Documentation
- Apple CoreGraphics Documentation
This is a research document. All APIs described are publicly documented or discoverable through standard reverse engineering techniques. No proprietary source code is included.