Publicado em 3 de julho de 2026
Se você já usou um editor de documentos, um app de planilha ou qualquer outro app em que colar conteúdo da área de transferência seja uma interação principal, você conhece a expectativa do usuário: a colagem precisa ser instantânea.
Infelizmente, em muitos casos, os apps da Web leem mais dados da área de transferência do que precisam, o que pode tornar a colagem de conteúdo mais lenta do que deveria, desperdiça ciclos de CPU e usa memória para dados que o app nunca precisa.
A leitura seletiva de formato resolve esse problema de performance modificando a API Async Clipboard para atender melhor às expectativas do usuário e fornecer o que os desenvolvedores precisam: ler apenas os formatos de que o app realmente precisa.
O problema: ler todos os formatos de dados antecipadamente
Quando um usuário copia de qualquer app, por exemplo, Excel, Documentos Google ou Photoshop, o app geralmente grava várias representações dos mesmos dados na área de transferência do sistema: texto simples, HTML, imagem e, às vezes, formatos personalizados. O app da Web que lê os dados (quando o usuário cola da área de transferência) raramente precisa de todas essas representações. Um editor de planilhas pode querer HTML. Um editor de texto pode querer expor um comando "colar como texto simples". Um editor de código pode querer apenas o texto e nada mais.
Até agora,
navigator.clipboard.read()
buscava todas as representações disponíveis dos dados da área de transferência do sistema
executava a sanitização (que pode levar tempo, especialmente com grandes payloads de HTML ou
imagem) e mantinha os bytes na memória, mesmo para os formatos que o app
nunca usaria. Quanto maior o payload não utilizado, mais tempo o usuário precisava esperar e mais memória a guia consumia, exatamente quando a capacidade de resposta da colagem era mais importante.
A solução: apenas enumerar e ler sob demanda
No Chrome e no Edge 149,
ClipboardItem
objetos retornados pelo método navigator.clipboard.read() descrevem apenas
o que está na área de transferência, em vez de dar acesso aos dados imediatamente. Os
bytes reais de um determinado formato são lidos da área de transferência somente quando você chama
ClipboardItem.getType(mimeType).
A superfície da API não foi alterada. O mesmo código que você escreveu ontem ainda funciona hoje, oferecendo benefícios de performance imediatos:
// Enumerate the available MIME types.
// No payload is fetched yet.
const items = await navigator.clipboard.read();
for (const item of items) {
if (item.types.includes('text/html')) {
// Only read the HTML data.
// The data is fetched (and sanitized) here only.
const blob = await item.getType('text/html');
useThePastedHtml(await blob.text());
break;
}
// text/plain, image/png, or any other custom formats
// stored in the clipboard are never read.
}
Outro benefício de performance aqui é que o armazenamento em cache é automático. Chamar
getType('text/html') duas vezes no mesmo ClipboardItem lê da área de transferência do sistema
apenas uma vez e retorna o Blobarmazenado em cache na segunda chamada.
Os benefícios
Latência. O trabalho que precisava acontecer quando navigator.clipboard.read() era chamado, como copiar bytes entre processos, sanitizar HTML ou decodificar imagens, agora só acontece para os formatos de que seu app realmente precisa. Os apps que leem apenas um formato recebem a maior parte da economia. Quanto maiores os formatos ignorados, maior o ganho. O HTML é o mais beneficiado porque a sanitização de HTML é cara.
Memória. Anteriormente, chamar navigator.clipboard.read() quando a área de transferência continha uma imagem de 50 MB significava que 50 MB precisavam ser usados na memória do renderizador da página da Web até que o ClipboardItem fosse liberado, mesmo que o app só precisasse da representação text/plain dos dados. Agora, apenas os formatos que seu app lê ao chamar ClipboardItem.getType() usam memória no processo do renderizador. Para apps em que a colagem é comum, como editores de documentos, compositores de e-mail ou ferramentas de design, isso reduz significativamente o uso de memória durante a colagem, especialmente em sessões com várias guias em que vários editores podem estar lendo a área de transferência em paralelo.
Sem ativação. Todos os sites da Web recebem esses benefícios automaticamente. Não é necessário migrar o código ou o código do portão por trás da lógica de detecção de recursos.
Uma mudança de comportamento a ser observada
A leitura dos dados mais tarde introduz uma pequena mudança no comportamento: um objeto ClipboardItem não é mais um snapshot congelado da área de transferência no momento em que a chamada para navigator.clipboard.read() foi resolvida.
Quando read() é chamado e retorna um ClipboardItem, esse item é apenas um handle lazy para os dados na área de transferência do sistema.
Se o conteúdo da área de transferência mudar entre a chamada para read() e uma chamada posterior para getType(), essa chamada será rejeitada com um InvalidStateError. Isso é verdadeiro mesmo para um formato que você leu anteriormente com sucesso no mesmo ClipboardItem.
// Read from the clipboard.
const items = await navigator.clipboard.read();
// Get the first ClipboardItem.
const item = items[0];
// Actually fetch the data now, which works fine.
const text = await item.getType('text/plain');
// The user writes something new to the clipboard
// by copying from another app, or your own code writes to
// the clipboard again.
await navigator.clipboard.writeText('something new');
// Fetching the data from the earlier ClipboardItem
// rejects with InvalidStateError, because the contents
// of the clipboard changed.
const html = await item.getType('text/html');
Isso acontece porque retornar dados que não refletem mais a área de transferência seria confuso e levaria a problemas difíceis de depurar.
Na prática, a mudança é invisível para a maioria dos códigos, porque os apps normalmente chamam read() e getType() consecutivamente no mesmo gerenciador de colagem. No entanto, talvez você queira observar casos em que há um código que mantém um ClipboardItem em limites assíncronos.
Confira um exemplo em que essa mudança pode se tornar um problema: armazenar objetos ClipboardItem em window, mostrá-los em uma interface de histórico da área de transferência ou aguardar a interação do usuário antes de chamar getType(). Para evitar problemas com um cenário como este:
- Encapsule as chamadas
getType()em blocostry / catche trateInvalidStateErrorcomo um sinal de que a área de transferência foi movida e o código precisa ser lido novamente. - Se você precisar reter dados da área de transferência, copie o
Blobpara sua própria estrutura assim quegetType(). Não trate oClipboardItemcomo armazenamento de longo prazo. - Use o
clipboardChangeevento para invalidar proativamente os identificadores obsoletos.
Padrões e suporte do navegador
A leitura seletiva de formato é uma mudança de especificação das APIs Clipboard impulsionada pelo Grupo de trabalho de edição da Web e pela equipe da plataforma da Web do Microsoft Edge.
O Safari também oferece suporte a esse comportamento, e o Firefox indicou uma posição e intenção de alinhamento de padrões positivos.
Uma melhoria de performance e interoperabilidade silenciosa, mas significativa, para a API Clipboard, com o Chromium agora convergindo para o mesmo modelo.