L'API Clipboard JavaScript
Apprenez l'API Clipboard JavaScript asynchrone — copiez et lisez du texte avec navigator.clipboard, gérez les données enrichies avec ClipboardItem et les exigences de contexte sécurisé et de permissions.
L'API Clipboard moderne, exposée via navigator.clipboard, est la méthode asynchrone et basée sur les promesses pour lire et écrire dans le presse-papiers système. Elle remplace l'ancienne approche synchrone document.execCommand('copy') par des méthodes qui retournent des promesses, ce qui les rend naturellement compatibles avec async/await. L'API est distincte — mais souvent utilisée conjointement — des événements clipboard cut, copy et paste : les événements vous permettent d'intercepter ce que fait l'utilisateur, tandis que navigator.clipboard permet à votre code d'initier des actions sur le presse-papiers directement.
Écrire du texte dans le presse-papiers
La tâche la plus courante est de copier du texte. navigator.clipboard.writeText(text) accepte une string, l'écrit dans le presse-papiers et retourne une Promise qui se résout lorsque l'écriture réussit et se rejette en cas d'échec.
Comme elle retourne une promesse, la façon la plus propre de l'utiliser est à l'intérieur d'une fonction async avec try...catch, afin de pouvoir donner un retour visuel à l'utilisateur dans les deux cas :
<button id="copyBtn">Copy</button>
<span id="status"></span>
<script>
const button = document.getElementById('copyBtn');
const status = document.getElementById('status');
button.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText('Hello from W3docs!');
status.textContent = 'Copied!';
} catch (err) {
status.textContent = 'Copy failed';
console.error('Clipboard write failed:', err);
}
});
</script>Le await met en pause jusqu'à ce que l'écriture dans le presse-papiers soit terminée. Si l'utilisateur a refusé la permission ou si la page n'est pas dans un contexte sécurisé, la promesse se rejette et le bloc catch s'exécute — c'est pourquoi vous ne devez jamais supposer que la copie a réussi.
Lire du texte depuis le presse-papiers
Pour lire le texte actuel du presse-papiers, appelez navigator.clipboard.readText(). Elle retourne également une promesse, qui se résout cette fois avec le contenu textuel du presse-papiers :
<button id="pasteBtn">Read clipboard</button>
<p id="output"></p>
<script>
const button = document.getElementById('pasteBtn');
const output = document.getElementById('output');
button.addEventListener('click', async () => {
try {
const text = await navigator.clipboard.readText();
output.textContent = `Clipboard contains: ${text}`;
} catch (err) {
output.textContent = 'Could not read clipboard';
console.error('Clipboard read failed:', err);
}
});
</script>La lecture est bien plus sensible que l'écriture, car elle expose ce que l'utilisateur a copié — peut-être un mot de passe ou d'autres données privées. Pour cette raison, les navigateurs protègent readText() de manière plus stricte : cela nécessite un geste explicite de l'utilisateur, et certains navigateurs affichent une invite de permission la première fois, ou n'autorisent les lectures que lorsque l'onglet de la page est actif.
Exigences et points d'attention
L'API Clipboard a plusieurs règles qui, si elles sont ignorées, entraînent des rejets silencieux. Gardez ces éléments à l'esprit chaque fois que vous l'utilisez.
L'API Clipboard ne fonctionne que dans un contexte sécurisé — cela signifie HTTPS, ou localhost en développement. Sur une page http:// simple, navigator.clipboard est généralement undefined. Les appels nécessitent également en général un geste de l'utilisateur comme un clic ou une pression de touche, donc les déclencher au chargement de la page échouera. L'API Permissions régit les permissions clipboard-read et clipboard-write, et les lectures peuvent inviter l'utilisateur. Comme tout appel peut se rejeter — permission refusée, document non focalisé ou navigateur non pris en charge — enveloppez toujours les appels au presse-papiers dans try...catch.
La page doit également être active pour de nombreuses opérations sur le presse-papiers. Si vous appelez readText() depuis, par exemple, un setTimeout pendant que l'utilisateur a changé d'onglet, attendez-vous à un rejet avec une erreur "document is not focused". Notez également qu'une lecture du presse-papiers ne se produit qu'après que l'utilisateur a focalisé et interagi avec votre page.
Copier des données enrichies avec ClipboardItem
Le texte est le cas simple. Pour copier des données non textuelles — images, HTML ou plusieurs formats à la fois — utilisez navigator.clipboard.write(), qui prend un array d'objets ClipboardItem. Chaque ClipboardItem associe des types MIME à leurs données (généralement un Blob).
L'exemple ci-dessous récupère une image, enveloppe le Blob résultant dans un ClipboardItem et le copie :
async function copyImage(url) {
try {
const response = await fetch(url);
const blob = await response.blob();
const item = new ClipboardItem({ [blob.type]: blob });
await navigator.clipboard.write([item]);
console.log('Image copied to clipboard');
} catch (err) {
console.error('Failed to copy image:', err);
}
}La clé à l'intérieur du constructeur ClipboardItem est le type MIME (ici blob.type, par exemple 'image/png'), et la valeur est la donnée pour ce type. Un seul élément peut contenir plusieurs représentations — par exemple à la fois 'text/plain' et 'text/html' — permettant à l'application de destination de choisir la meilleure.
La lecture de données enrichies suit le même principe avec navigator.clipboard.read(), qui se résout en un array d'objets ClipboardItem que vous inspectez par type :
async function readClipboardItems() {
const items = await navigator.clipboard.read();
for (const item of items) {
for (const type of item.types) {
const blob = await item.getType(type);
console.log(`Found ${type}`, blob);
}
}
}La prise en charge par les navigateurs des méthodes pour données enrichies (write et read avec ClipboardItem) est plus limitée et moins cohérente que pour les méthodes textuelles. Les types MIME d'images varient notamment selon les navigateurs — image/png est le plus fiable. Détectez la fonctionnalité avec if ('write' in navigator.clipboard) et repliez-vous sur la copie de texte ou d'une URL lorsque les données enrichies ne sont pas disponibles.
La solution de repli héritée
Avant l'API asynchrone, copier signifiait sélectionner un élément et appeler document.execCommand('copy'). Cette méthode est désormais dépréciée, mais elle fonctionne encore dans les anciens navigateurs, ce qui la rend utile uniquement comme solution de repli. Le schéma typique sélectionnait un <textarea> caché, puis exécutait la commande :
function copyTextFallback(text) {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy'); // deprecated
document.body.removeChild(textarea);
}Le code moderne doit préférer l'API asynchrone et ne se replier que lorsque navigator.clipboard est absent :
async function copyText(text) {
if (navigator.clipboard) {
await navigator.clipboard.writeText(text);
} else {
copyTextFallback(text);
}
}Utilisations concrètes
L'API Clipboard alimente de nombreuses interactions petites mais précieuses que vous voyez au quotidien :
- Les boutons "Copier le code" sur les pages de documentation, pour que les lecteurs puissent récupérer un extrait sans sélection manuelle.
- Les boutons "Copier le lien à partager" qui placent une URL dans le presse-papiers pour la coller dans un chat ou un e-mail.
- La copie de résultats générés, comme un mot de passe, une clé d'API ou une citation formatée.
Quelle que soit la chose copiée, donnez un retour visuel. Un bouton qui copie silencieusement laisse les utilisateurs incertains quant au résultat. Changez le libellé en "Copié !", affichez un bref message ou mettez à jour un élément de statut adjacent — c'est également un atout pour l'accessibilité, car les utilisateurs de lecteurs d'écran ne reçoivent aucun signal du presse-papiers de la part du navigateur lui-même.