Technical

How NSPasteboard Works — A Deep Dive into macOS Clipboard

NSPasteboard is the API behind every copy and paste on macOS. Here's how it works — pasteboard types, UTIs, change count polling, and how clipboard managers monitor it.

How NSPasteboard Works — A Deep Dive into macOS Clipboard
Technical | | 5 min read

Every time you press ⌘C on a Mac, you're interacting with NSPasteboard — the AppKit class that has powered copy and paste on macOS since the NeXTSTEP days. It's one of the oldest APIs in the system, and it's deceptively simple on the surface. But underneath, there's a surprisingly rich data model that most developers never explore.

If you've ever wondered how clipboard managers detect new copies, how a single copy operation can carry both plain text and rich text simultaneously, or why there's no notification API for clipboard changes — this is the deep dive.

What is NSPasteboard?

NSPasteboard is a shared, system-wide data broker. When an app copies data, it writes one or more representations of that data to a pasteboard. When another app pastes, it reads the representation it prefers. The pasteboard is the intermediary — the two apps never communicate directly.

The API is straightforward. Writing looks like this:

let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.setString("Hello, world", forType: .string)

Reading is equally simple:

if let string = NSPasteboard.general.string(forType: .string) {
    print(string)
}

But this simplicity hides the real power of the system — multiple types, multiple items, and lazy data providing.

Pasteboard types

macOS has several distinct pasteboards, each serving a different purpose:

For clipboard management, only NSPasteboard.general matters. But the find pasteboard is worth knowing about — it's one of macOS's best hidden features.

UTIs and data representation

When you copy formatted text from a web page, the pasteboard doesn't just store one thing. It stores multiple representations of the same content — HTML, RTF, plain text, and sometimes more. The pasting app chooses which representation to use.

These representations are identified by Uniform Type Identifiers (UTIs), now formalized as UTType in the UniformTypeIdentifiers framework. Common ones include:

  • public.utf8-plain-text — plain text
  • public.html — HTML markup
  • public.rtf — Rich Text Format
  • public.png — PNG image data
  • public.file-url — file path as a URL

A single copy operation can place a dozen different representations on the pasteboard. The pasting app picks the richest format it understands.

This is why pasting into a code editor gives you plain text while pasting into Pages gives you formatted text — same pasteboard data, different type preference.

Change count and monitoring

Here's the critical detail for clipboard manager developers: macOS has no notification API for pasteboard changes. There's no NSNotification, no delegate callback, no Combine publisher. The only way to know the clipboard changed is to poll.

NSPasteboard.general.changeCount is an integer that increments every time the pasteboard contents change. A clipboard manager's core loop looks like this:

var lastChangeCount = NSPasteboard.general.changeCount

Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
    let current = NSPasteboard.general.changeCount
    if current != lastChangeCount {
        lastChangeCount = current
        // New clipboard content — read and store it
    }
}
Key detail

Change count behavior

The change count also increments when clearContents() is called, even if no new data is written. Clipboard managers need to handle the case where the pasteboard was cleared but has no readable content. Always check for valid data after detecting a change.

The polling interval is a tradeoff. Too fast and you waste CPU. Too slow and the user copies something, pastes it, and the manager never saw it. Most clipboard managers — including QuietClip — poll every 0.3 to 0.5 seconds. The CPU cost is negligible since checking changeCount is a single integer comparison.

Multiple items on the pasteboard

NSPasteboard can hold multiple items simultaneously, each with its own set of type representations. This is most commonly used during drag-and-drop — select ten files in Finder, drag them, and the pasteboard contains ten items, each with a file URL.

let items = NSPasteboard.general.pasteboardItems ?? []
for item in items {
    for type in item.types {
        print("Type: \(type.rawValue)")
    }
}

For clipboard managers, multi-item pasteboards need special handling. When a user copies ten files, you probably want to store that as a single history entry — not ten separate ones.

How clipboard managers use NSPasteboard

A clipboard manager like QuietClip builds on everything above. The core workflow is:

  1. Poll changeCount on a timer
  2. When it changes, read all available types from the pasteboard
  3. Store the data persistently (QuietClip uses SwiftData)
  4. When the user wants to re-paste an old item, write it back to the pasteboard
  5. Simulate ⌘V using CGEvent to paste it into the active app

Step 5 is why clipboard managers need Accessibility permissions — they're synthesizing keystrokes. But the pasteboard reading itself requires no special permissions. Any app can read NSPasteboard.general at any time.

Privacy note

Because any app can read the clipboard, privacy-conscious clipboard managers like QuietClip store history locally and never transmit pasteboard contents over the network. The clipboard is a shared resource — the manager's job is to keep your data local.

The NSPasteboard API hasn't changed much in decades, and it probably won't. It's a simple, stable foundation — which is exactly what you want from something that runs thousands of times a day on every Mac.

Next step

A clipboard manager built on these fundamentals.

QuietClip uses NSPasteboard polling, SwiftData persistence, and zero network code. Your clipboard history stays on your Mac. Free to start, $8.99 once for Pro.

Download QuietClip Free

Frequently asked questions

Is there a notification for clipboard changes on macOS?
No. macOS does not provide a notification or callback when the pasteboard changes. Apps must poll NSPasteboard.general.changeCount on a timer to detect new content. This is the official Apple-recommended approach.
What's the difference between NSPasteboard and UIPasteboard?
NSPasteboard is the macOS AppKit API. UIPasteboard is the iOS UIKit equivalent. They serve the same purpose but have different APIs and security models — iOS restricts background pasteboard access for privacy.
Can NSPasteboard hold multiple items at once?
Yes. NSPasteboard supports multiple pasteboard items, each with its own set of type representations. This is commonly used for drag-and-drop operations where you select multiple files.
What happens to pasteboard data when an app quits?
The data persists. When you copy something, macOS stores the data in a system-managed buffer. The source app can quit and the data remains available for pasting — unless the app used lazy providing (promised data) and quit before fulfilling the promise.

Try QuietClip free

A privacy-first clipboard manager for macOS. Your data stays on your device, always.

Download for macOS

Related reads