1. Introduction
This section is non-normative.
This specification defines how the system clipboard is exposed to web applications.
There are two general APIs described in this specification:
-
Clipboard Event API - This API provides a way to hook into the common clipboard operations of cutting, copying and pasting so that web application can adjust the clipboard data as required.
-
Async Clipboard API - This API provides direct access to read and write the clipboard data. Since this is considered to be a powerful feature, access to this API is controlled by a permission.
2. Use Cases
This section is non-normative.
2.1. Changing Default Clipboard Operations
There are many scenarios where it is desireable to change the default clipboard operations (cut/copy/paste). Here are a few examples:
- Metadata When copying text from a repository of documents, it can be useful for the copied text to include metadata about the source of the copied content.
- Rich content editing When copying text which contains hyperlinks or other structure, it is often useful to be able to reformat the content to preserve important information.
- Graphics with built-in semantics In order to make web applications which allow the manipulation of rich text, or of graphic content such as [SVG11], it is useful to provide a mechanism that allows for copying more than just the rendered content.
- Mathematical information With content such as mathematics, simply copying rendered text and pasting it into another application generally leads to most of the semantics being lost. MathML often needs to be transformed to be copied as plain text, for example to make sure "to the power of" is shown with the caret "^" sign in a formula plain-text input. The XML source could also be placed in the clipboard with the appropriate transformation occurring at paste time.
2.2. Remote Clipboard Synchronization
For web applications that communicate with remote devices (e.g., remote access or remote shell applications), there is often a need for the clipboard data to be kept in sync between the two devices.
One important aspect of this use case is that it requires access to the clipboard in the absense of a user gesture or interaction.
write()
the data to the local clipboard.
clipboardchange events, read() from the clipboard
whenever it is updated, and then send the new clipboard data to the remote device.
2.3. Trigger Clipboard Actions
Applications that provide an alternate interface to a user agent sometimes need to be able to trigger clipboard actions in the user agent.
As an example, consider a screen reader application that provides a more accessible interface to a standard web browser. While the reader can display content and allow the user to interact with it, actions like clipboard copy need to occur in the underlying browser to ensure that the clipboard content is set correctly (with any metadata added by the browser during copy).
3. Terminology
The term editable context means any element that is either an editing host, a textarea element, or an input element with its type attribute set to any of "text", "search", "tel", "url", "email", "password" or "number".
4. Model
The platform provides a system clipboard.
The system clipboard has a list of system clipboard items that are collectively called the system clipboard data.
Each system clipboard item has a list of system clipboard representations.
Each system clipboard representation has a name, which is a string, and data, which is a sequence of bytes.
The system clipboard has a clipboard change count, which is a value that changes each time the system clipboard data is modified.
5. Clipboard Events
5.1. Clipboard event interfaces
The ClipboardEvent interface extends the Event interface.
dictionary :ClipboardEventInit EventInit {DataTransfer ?=clipboardData null ; };
- clipboardData
-
A
DataTransferobject to hold data and meta data related to the event.
[Exposed =Window ]interface :ClipboardEvent Event {(constructor DOMString ,type optional ClipboardEventInit = {});eventInitDict readonly attribute DataTransfer ?; };clipboardData
- clipboardData
-
The clipboardData attribute is an instance of the
DataTransferinterface which lets a script read and manipulate values on the system clipboard during user-initiated copy, cut and paste operations. The associated drag data store is a live but filtered view of the system clipboard, exposing mandatory data types the implementation knows the script can safely access. For synthetic events, the drag data store contains the data added by the script that created the event.The clipboardData object’s
itemsandfilesproperties enable processing of multi-part or non-textual data from the clipboard.
The interface can be used to construct events. An example is given below:
var pasteEvent = new ClipboardEvent('paste');
pasteEvent.clipboardData.items.add('My string', 'text/plain');
document.dispatchEvent(pasteEvent);
Note: Synthetic clipboard events will not actually modify the clipboard or the document. In other words, while the script above will fire a paste event, the data will not be pasted into the document.
5.2. Clipboard events
5.2.1. The clipboardchange event
The clipboardchange event fires whenever the contents of the
system clipboard are changed. These changes could be due to any of the
following (non-exhaustive):
-
User-initiated cut or copy actions
-
Scripts that use the § 7 Asynchronous Clipboard API to write to the clipboard
-
Actions that update the clipboard outside the user agent
5.2.1.1. To fire a clipboardchange event
To fire a clipboardchange event given a Document document:
-
If document does not have sticky activation and document does not have permission to read from the clipboard, then return.
-
Let global be document’s relevant global object.
-
If document has system focus:
-
Let types be a list of mandatory data types available on the system clipboard.
-
Let changeId be the result of running generate a changeId given document.
-
Let eventInit be a new
ClipboardChangeEventInitdictionary with itstypesmember set to types and itschangeIdmember set to changeId. -
Fire an event named
clipboardchangeat global, usingClipboardChangeEvent, with eventInit.
-
-
If document does not have system focus:
-
Set document’s clipboardchange pending flag to true.
-
User agents MAY choose to skip firing clipboardchange events for clipboard changes that have been superseded by more recent changes before the event would be delivered. This optimization can improve performance in scenarios where clipboard changes occur in rapid succession, as delivering obsolete change notifications provides no value to web applications while consuming processing resources.
5.2.1.2. Document focus steps
When a Document document gains system focus:
-
If document’s clipboardchange pending flag is true:
-
Set document’s clipboardchange pending flag to false.
-
Let types be a list of mandatory data types available on the system clipboard.
-
Let changeId be the result of running generate a changeId given document.
-
Let eventInit be a new
ClipboardChangeEventInitdictionary with itstypesmember set to types and itschangeIdmember set to changeId. -
Let global be document’s relevant global object.
-
Fire an event named
clipboardchangeat global, usingClipboardChangeEvent, with eventInit.
-
For documents in nested browsing contexts, the clipboardchange event fires independently in each Document based on its own focus state. A clipboard change will fire an event in the single document that has system focus (if that document has sticky activation or persistent clipboard permissions).
Note: The clipboardchange event is only available after sticky activation, unless the document has persistent permission to read from the clipboard. In user agents that support persistent clipboard permissions, sites with such permissions can receive clipboardchange events without sticky activation, as the permission already grants access to more sensitive clipboard data.
The changeId provides a unique identifier for each clipboard change operation. For the same clipboard change, all windows and tabs with the same storage key will receive events with identical changeId values, enabling applications with multiple windows to deduplicate events and avoid redundant processing. The identifier is storage key-specific and does not provide cross-storage key correlation capabilities.
The clipboardchange event does not bubble and is not cancelable, as it
is not triggered by a user action but rather by changes to the system clipboard state.
dictionary :ClipboardChangeEventInit EventInit {sequence <DOMString >= [];types bigint = 0; };changeId
- types
-
A sequence of
DOMStringrepresenting the mandatory data types available on the system clipboard. - changeId
-
A
bigintrepresenting a unique identifier for the clipboard change operation.
[Exposed =Window ]interface :ClipboardChangeEvent Event {(constructor DOMString ,type optional ClipboardChangeEventInit = {});eventInitDict readonly attribute FrozenArray <DOMString >;types readonly attribute bigint ; };changeId
- types
-
Returns a
FrozenArrayofDOMStringobjects indicating the mandatory data types available on the system clipboard when the event was fired. Optional data types and custom formats are excluded to limit fingerprinting surface. - changeId
-
Returns a
bigintrepresenting a unique identifier for this specific clipboard change operation. This identifier is consistent across all windows and tabs with the same storage key for the same clipboard change, enabling applications to deduplicate events when multiple windows receive the same clipboard change notification.The
changeIdis a cryptographically derived 128-bit integer. The only guarantee is that after something is written to the clipboard,changeIdwill yield a different value than it did before the write operation.
5.2.1.3. ClipboardChangeEvent constructor steps
The ClipboardChangeEvent(type, eventInitDict) constructor steps are:
5.2.1.4. ChangeId Generation
To generate a changeId for a Document document:
-
Let globalChangeId be a user agent-specific unique identifier representing the current state of the system clipboard. This identifier changes each time the system clipboard is modified, and is reset when the user agent restarts.
-
Let storageKey be the result of running obtain a storage key for non-storage purposes given document’s relevant settings object.
-
Let storageKeyBytes be some user agent-specific binary representation of storageKey.
-
Let hashedValue be the result of applying a cryptographic hash function (such as SHA-256) to the concatenation of globalChangeId (as bytes) and storageKeyBytes.
-
Return a 128-bit integer derived from hashedValue (for example, by taking the first 128 bits of the hash output).
The above algorithm ensures that documents from the same origin and with the same partitioning receive identical change IDs for the same clipboard modification, enabling proper event deduplication across multiple windows and tabs, while preventing cross-partition correlation that could be used for tracking. As Client-side Storage Partitioning changes are incorporated into the storage key definition, this approach will automatically provide anonymization across partitions.
The changeId does not persist across browser restarts, as the globalChangeId counter is reset when the user agent restarts. Similarly, when a user clears site data, the affected tabs should be refreshed, which causes event listeners to be re-attached and only receive future events with new change IDs.
Since synthetic cut and copy events do not update the system clipboard,
they will not trigger a "clipboardchange" event.
clipboardchange event enables web applications to efficiently monitor
clipboard changes and provide dynamic user interfaces based on available data formats:
// For applications with multiple windows, track processed change IDs to avoid duplication
const processedChangeIds = new Set();
// Listen for clipboard changes
navigator.clipboard.addEventListener('clipboardchange', (e) => {
// Deduplicate events across multiple windows using changeId
if (processedChangeIds.has(e.changeId)) {
return; // This change has already been processed
}
processedChangeIds.add(e.changeId);
// Check what data types are available on the clipboard
const hasText = e.types.includes('text/plain');
const hasHTML = e.types.includes('text/html');
const hasImage = e.types.includes('image/png');
// Update UI based on available formats
document.getElementById('paste-text-btn').disabled = !hasText;
document.getElementById('paste-html-btn').disabled = !hasHTML;
document.getElementById('paste-image-btn').disabled = !hasImage;
// For remote desktop apps, sync clipboard to remote only once per change
if (hasText || hasHTML || hasImage) {
syncClipboardToRemote(e.changeId);
}
});
// Alternatively, you can use the onclipboardchange property
// navigator.clipboard.onclipboardchange = (e) => { ... };
This event-driven approach is more efficient than polling the clipboard with methods like
read() or readText() and works across browsers that require user activation
for clipboard access, as the UI can react instantly to clipboard changes without waiting for a timer to fire.
The changeId is particularly useful for applications with multiple windows,
ensuring that each clipboard change is processed only once across all windows with the same storage key.
5.2.2. The copy event
When the user initiates a copy action, the user agent
fires a clipboard event named
copy.
If the event is not canceled, the currently selected data will be copied to the system clipboard. The current document selection is not affected.
The copy event bubbles, is cancelable, and is composed.
See § 8.1 The copy action for a detailed description of the processing model for this event.
A synthetic copy event can be manually constructed and dispatched, but it
will not affect the contents of the system clipboard.
5.2.3. The cut event
When the user initiates a cut action, the user agent
fires a clipboard event named
cut.
In an editable context, if the event is not
canceled the action will place the currently selected data on the
system clipboard and remove the selection from the document.
The cut event fires before the selected data is removed. When
the cut operation is completed, the selection is collapsed.
In a non-editable context, the clipboardData will
be an empty list. Note that the cut event will still be fired
in this case.
The cut event bubbles, is cancelable, and is composed.
See § 8.2 The cut action for a detailed description of the processing model for this event.
A synthetic cut event can be manually constructed and dispatched, but it
will not affect the contents of the document or of the system clipboard.
5.2.4. The paste event
When a user initiates a paste action, the user agent
fires a clipboard event named
paste. The event fires before any clipboard data is inserted
into the document.
If the cursor is in an editable context, the paste action will insert clipboard data in the most suitable format (if any) supported for the given context.
The paste action has no effect in a non-editable context,
but the paste event fires regardless.
The paste event bubbles, is cancelable, and is composed.
See § 8.3 The paste action for a detailed description of the processing model for this event.
A synthetic paste event can be manually constructed and dispatched, but it
will not affect the contents of the document.
5.3. Integration with other scripts and events
5.3.1. Event handlers that are allowed to modify the clipboard
Event handlers may write to the clipboard if any of the following is true:
-
The action which triggers the event is invoked from the user-agent’s own user interface, e.g. from a "Copy" menu entry or shortcut key.
-
The action which triggers the event is invoked from a scripting thread which is allowed to show a popup.
The implementation may allow other trusted event types to modify the clipboard if the implementation authors believe that those event types are likely to express user intention. The implementation may also support configuration that trusts specific sites or apps to modify the clipboard regardless of the origin of the scripting thread.
Synthetic cut and copy events must not modify data on the
system clipboard.
5.3.2. Event handlers that are allowed to read from clipboard
Event handlers may read data from the system clipboard if either of the following is true
-
The action that triggers the event is invoked from the user-agent’s own user interface, e.g. a "Paste" menu entry or shortcut key.
-
The script that triggers the action is running on a site which through an implementation-dependant mechanism is given permission to read data from the clipboard.
-
The action that triggers the event is triggered in an app with permissions to read the clipboard.
Synthetic paste events must not give a script access to data on
the real system clipboard.
5.3.3. Integration with rich text editing APIs
If an implementation supports ways to execute clipboard commands through
scripting, for example by calling the
document.execCommand() method with the commands "cut",
"copy" and "paste", the implementation must trigger the
corresponding action, which again will dispatch the associated clipboard
event.
These are the steps to follow when triggering copy, cut or paste actions through a scripting API:
-
Execute the corresponding action synchronously.
-
Use the action’s return value as the return value for the API call.
Note: Copy and cut commands triggered through a scripting API will only affect the contents of the real clipboard if the event is dispatched from an event that is trusted and triggered by the user, or if the implementation is configured to allow this. Paste commands triggered through a scripting API will only fire paste events and give access to clipboard contents if the implementation is configured to allow this. How implementations can be configured to allow read or write access to the clipboard is outside the scope of this specification.
5.3.4. Interaction with other events
If the clipboard operation is triggered by keyboard input, the implementation must fire the corresponding event that initiates the clipboard operation. The event is asynchronous but must be dispatched before keyup events for the relevant keys.
The cut and paste actions may cause the implementation to dispatch other supported events, such as textInput, input, change, validation events, DOMCharacterDataModified and DOMNodeRemoved / DOMNodeInserted. Any such events are queued up to fire after processing of the cut/paste event is finished.
The implementation must not dispatch other input-related events like textInput, input, change, and validation events in response to the copy operation.
5.3.5. Event listeners that modify selection or focus
If the event listener modifies the selection or focusable area, the clipboard action must be completed on the modified selection.
6. Clipboard Event API
The Clipboard Event API allows you to override the default cut, copy and paste behavior of the user agent.
Access to the clipboard is performed using the standard
DataTransfer methods to mutate the items on a
ClipboardEvent’s clipboardData attribute.
One consequence of this is that these clipboard APIs can only
access clipboard data in the context of a ClipboardEvent handler.
Note: If you need to access the clipboard outside of a clipboard event handler, see § 7 Asynchronous Clipboard API.
Note: The Clipboard Event APIs are synchronous, so they are limited in what they can do. Actions which are potentially blocking (like asking for permission or transcoding a image) are not supported by these APIs. See § 7 Asynchronous Clipboard API for a more powerful API that can support blocking or other time-consuming actions.
6.1. Overriding the copy event
To override the default copy event behavior, a copy event
handler must be added and this event handler must call
preventDefault() to cancel the event.
Canceling the event is required in order for the system clipboard to be
updated with the data in clipboardData.
If the ClipboardEvent is not canceled, then the data from the
current document selection will be copied instead.
// Overwrite what is being copied to the clipboard.
document.addEventListener('copy', function(e) {
// e.clipboardData is initially empty, but we can set it to the
// data that we want copied onto the clipboard.
e.clipboardData.setData('text/plain', 'Hello, world!');
e.clipboardData.setData('text/html', '<b>Hello, world!</b>');
// This is necessary to prevent the current document selection from
// being written to the clipboard.
e.preventDefault();
});
6.2. Overriding the cut event
To override the default cut event behavior, a cut event
handler must be added and this event handler must call
preventDefault() to cancel the event.
Canceling the event is required in order for the system clipboard to be
updated with the data in clipboardData.
If the ClipboardEvent is not canceled, then the data from the
current document selection will be copied instead.
Note that canceling the cut event will also prevent the document from
being updated (i.e., the current selection will not be removed). The event
handler will need to manually update the document to remove the currently
selected text.
// Overwrite what is copied to the clipboard.
document.addEventListener('cut', function(e) {
// e.clipboardData is initially empty, but we can set it to the
// data that we want copied onto the clipboard as part of the cut.
// Write the data that we want copied onto the clipboard.
e.clipboardData.setData('text/plain', 'Hello, world!');
e.clipboardData.setData('text/html', '<b>Hello, world!</b>');
// Since we will be canceling the cut operation, we need to manually
// update the document to remove the currently selected text.
deleteCurrentDocumentSelection();
// This is necessary to prevent the document selection from being
// written to the clipboard.
e.preventDefault();
});
6.3. Overriding the paste event
To override the default paste event behavior, a paste event
handler must be added and this event handler must call
preventDefault() to cancel the event.
Canceling the event is required so that the user agent does not update the document with data from the system clipboard.
Note that canceling the paste event will also prevent the document from
being updated (i.e., nothing will be pasted into the document). The event
handler will need to manually paste the data into the document.
Also note that, when pasting, the drag data store mode flag is
read-only, hence calling setData() from a
paste event handler will not modify the data that is
inserted, and not modify the data on the clipboard.
// Overwrite what is being pasted onto the clipboard.
document.addEventListener('paste', function(e) {
// e.clipboardData contains the data that is about to be pasted.
if (e.clipboardData.types.indexOf('text/html') > -1) {
var oldData = e.clipboardData.getData('text/html');
var newData = '<b>Ha Ha!</b> ' + oldData;
// Since we are canceling the paste operation, we need to manually
// paste the data into the document.
pasteClipboardData(newData);
// This is necessary to prevent the default paste action.
e.preventDefault();
}
});
6.4. Mandatory data types
The implementation must recognize the native OS clipboard format description
for the following data types, to be able to populate the
DataTransferItemList and ClipboardItem with the correct description for
paste events, and set the correct data format on the OS clipboard in response to
copy and cut events.
6.4.1. Reading from the clipboard
These data types must be exposed by paste events if a corresponding native type exists on the clipboard:
-
text/plain
-
text/html
-
image/png
6.4.2. Writing to the clipboard
These data types must be placed on the clipboard with a corresponding
native type description if added to a DataTransfer object during
copy and cut events.
-
text/plain
-
text/html
-
image/png
Warning! The data types that untrusted scripts are allowed to write to the clipboard are limited as a security precaution. Untrusted scripts can attempt to exploit security vulnerabilities in local software by placing data known to trigger those vulnerabilities on the clipboard.
6.5. Optional data types
The implementation MAY recognize the native OS clipboard format description
for the following data types, to be able to populate the
ClipboardItem with the correct description for paste events, and
set the correct data format on the OS clipboard in response to copy and cut
events.
These data types MAY be exposed by UAs if a corresponding native type exists on the clipboard:
-
text/uri-list
-
image/svg+xml
-
Custom format starts with `"web "`("web" followed by U+0020 SPACE) prefix and suffix (after stripping out `"web "`) passes the parsing a MIME type check.
6.6. Unsanitized data types
This section is non-normative.These data types MUST NOT be sanitized by UAs:
-
image/png
These data types MAY NOT be sanitized by UAs:
Optional unsanitized data types are mime types specified by the web authors that MAY NOT be sanitized by the user agent. The valid optional unsanitized data types are listed below:
-
text/html
optional unsanitized data types may not be supported by a user agent due to their privacy requirements.
7. Asynchronous Clipboard API
7.1. Navigator Interface
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute Clipboard ; };clipboard
7.2. ClipboardItem Interface
typedef Promise <(DOMString or Blob )>; [ClipboardItemData SecureContext ,Exposed =Window ]interface {ClipboardItem constructor (record <DOMString ,ClipboardItemData >,items optional ClipboardItemOptions = {});options readonly attribute PresentationStyle presentationStyle ;readonly attribute FrozenArray <DOMString >types ;Promise <Blob >getType (DOMString );type static boolean supports (DOMString ); };type enum {PresentationStyle ,"unspecified" ,"inline" };"attachment" dictionary {ClipboardItemOptions PresentationStyle = "unspecified"; };presentationStyle
clipboardItem = new ClipboardItem([items, options])-
Creates a new
ClipboardItemobject. items denote list of representations, each representation has a mime type and aPromisetoBloborDOMStringcorresponding to the mime type, options can be used to fill itsClipboardItemOptions, as per the example below.const format1= 'text/plain' ; const promise_text_blob= Promise. resolve( new Blob([ 'hello' ], { type: format1})); const clipboardItemInput= new ClipboardItem( {[ format1] : promise_text_blob}, { presentationStyle: "unspecified" }); clipboardItem.getType(type)- Returns a
Promiseto theBlobcorresponding to the mime type type. clipboardItem.types- Returns the list of mime types contained in the clipboard item object.
ClipboardItem.supports(type)- Returns true if type is in mandatory data types or optional data types, else, returns false.
A clipboard item is conceptually data that the user has expressed a desire to make shareable by invoking a "cut" or "copy" command. A clipboard item serves two purposes. First, it allows a website to read data copied by a user to the system clipboard. Second, it allows a website to write data to the system clipboard.
For example, if a user copies a range of cells from a spreadsheet of a native application, it will result in one clipboard item. If a user copies a set of files from their desktop, that list of files will be represented by multiple clipboard items.
Some platforms may support having more than one clipboard item at a time on the clipboard, while other platforms replace the previous clipboard item with the new one.
A clipboard item has a list of representations, each representation with an associated MIME type (a MIME type), an isCustom flag, initially false, that indicates if this representation should be treated as a web custom format (as opposed to a well-known format of the system clipboard), and data (a ClipboardItemData).
A web custom format has isCustom set to true.
In the example where the user copies a range of cells from a spreadsheet, it may be represented as an image (image/png), an HTML table (text/html), or plain text (text/plain), or a web custom format (web text/csv).
Each of these MIME types describe a different representation of the same clipboard item at different levels of fidelity and make the clipboard item more consumable by target applications during paste.
Making the range of cells available as an image will allow the user to paste the cells into a photo editing app, while the text/plain format can be used by text editor apps.
A clipboard item has a presentation style (a PresentationStyle). It helps distinguish whether apps "pasting" a clipboard item should insert the contents of an appropriate representation inline at the point of paste or if it should be treated as an attachment.
Web apps that support pasting only a single clipboard item should use the first clipboard item.
write() chooses the last clipboard item.
Web apps that support pasting more than one clipboard item could, for example, provide a user interface that previews the contents of each clipboard item and allow the user to choose which one to paste. Further, apps are expected to enumerate the MIME types of the clipboard item they are pasting and select the one best-suited for the app according to some app-specific algorithm. Alternatively, an app