Cómo Copiar Texto al Portapapeles con JavaScript con la API Clipboard

Copiar texto al portapapeles desde una página web puede parecer algo básico, pero detrás hay toda una API moderna y una serie de consideraciones de seguridad importantes. En esta guía te mostraré cómo implementar esta funcionalidad en JavaScript, con ejemplos reales, compatibilidad entre navegadores y algunos trucos que aprendí al aplicarlo en mis propios proyectos.

Cuando copiamos algo desde una aplicación o una web, estamos modificando el portapapeles de nuestro sistema operativo. Y aquí viene un punto muy importante: estamos accediendo al sistema operativo mediante JavaScript.

Te muestro cómo puedes modificar el portapapeles, es decir, cómo implementar la funcionalidad de copiar y pegar usando JavaScript.

¿Qué significa copiar al portapapeles en JavaScript?

Cuando copiamos algo —ya sea un texto, un enlace o un fragmento de código— estamos modificando el portapapeles del sistema operativo. Esto implica una pequeña “conversación” entre el navegador y el SO, algo que JavaScript puede hacer mediante la Clipboard API.

En mi caso, la primera vez que necesité esta funcionalidad fue para permitir que los usuarios copiaran fragmentos de código con un clic. Para ello, se emplea document.execCommand('copy'), ya que ese método está obsoleto. La solución moderna y más segura es navigator.clipboard.writeText().

Usando navigator.clipboard.writeText

La Clipboard API ofrece una forma sencilla y segura de copiar texto al portapapeles. El método navigator.clipboard.writeText() recibe el texto que quieres copiar y devuelve una promesa, porque se trata de una operación asíncrona que interactúa directamente con el sistema operativo.

navigator.clipboard.writeText("Tu texto aquí");

Este método recibe el texto que quieres copiar, y como es una operación que interactúa con el sistema operativo (algo que podría estar ocupado o requerir permisos), funciona como una promesa.

¿Por qué es una promesa?

Cada vez que accedemos a disco o al sistema operativo desde JavaScript, se utiliza una promesa, porque esas operaciones no se resuelven de inmediato.

Por eso aquí también estamos usando una promesa, que se resuelve cuando el texto se ha copiado correctamente al portapapeles. Si quieres hacer algo una vez que se haya copiado, puedes usar .then(), tal como lo hago yo, donde muestro un pequeño toast para notificarle al usuario que la acción se completó:

  btn.addEventListener('click', () => {
    this.$toast.success(this.$t('resource.copied') + "!");
    const text = pre.innerText;
    navigator.clipboard.writeText(text).then(() => {
      // btn.innerText = this.$t('resource.copied');
      this.$toast.success(this.$t('resource.copied') + "!");
    }).catch(err => {
      console.error('Error al copiar: ', err);
    });
  });

Consideraciones de seguridad: HTTPS y permisos del navegador

Un par de cosas que debes tener en cuenta:

  • Debes estar en HTTPS para que esto funcione correctamente. Por ejemplo, si trabajas en localhost con HTTPS (como https://localhost), no tendrás problemas.
  • Sin embargo, si estás en un entorno inseguro, como un virtual host con http (sin la "s"), te aparecerá un error como el que muestro en pantalla:
    • navigator.clipboard is null
  • Esto ocurre porque los navegadores bloquean el acceso al portapapeles en entornos inseguros. En mi caso, la primera vez que lo probé en un entorno local con HTTP, el método simplemente no respondía. Al activar HTTPS, todo funcionó correctamente.

Compatibilidad con navegadores

Si te preocupa que el navegador del usuario sea antiguo o no soporte esta API, puedes hacer una simple validación como esta:

if (navigator.clipboard) {
   // puedes usar clipboard.writeText
} else {
   // muestra un mensaje alternativo
}

Con esto puedes copiar y pegar contenido de forma sencilla usando JavaScript y ofrecer una mejor experiencia al usuario, siempre y cuando respetes los requerimientos de seguridad.

Mejorando la experiencia de usuario (UX)

Más allá de que funcione, es importante que el usuario sepa que el texto se copió correctamente. Puedes mostrar un mensaje, cambiar el texto del botón o lanzar un pequeño toast.

Otra mejora es usar async/await, que hace el código más limpio:

async function copiarTexto() {
 try {
   await navigator.clipboard.writeText("Texto copiado con éxito");
   alert("Texto copiado al portapapeles ✅");
 } catch (err) {
   console.error("No se pudo copiar:", err);
 }
}

También puedes copiar automáticamente al cargar la página o al hacer doble clic, aunque esto debe hacerse con precaución, ya que algunos navegadores lo bloquean si no hay interacción directa del usuario.

Errores comunes y cómo solucionarlos

Error    Causa probable    Solución
navigator.clipboard is undefined    Página sin HTTPS o contexto no seguro    Usa HTTPS o entorno localhost
Promesa rechazada    Permiso denegado o bloqueo del navegador    Reintentar tras interacción del usuario
Nada se copia    Código ejecutado fuera de un evento de usuario    Ejecuta dentro de un click o input

En mi experiencia, el error más habitual es ejecutar la función antes de que el usuario interactúe. Por seguridad, la mayoría de navegadores no permiten copiar sin acción explícita.

Preguntas frecuentes (FAQ)

  • ¿Por qué navigator.clipboard no funciona en HTTP?
    • Porque los navegadores solo habilitan la API Clipboard en sitios HTTPS o en localhost.
  • ¿Qué navegadores soportan clipboard.writeText()?
    • La mayoría de los navegadores modernos, excepto Internet Explorer.
  • ¿Cómo puedo mostrar un mensaje cuando el texto se copia?
    • Puedes usar alert(), un toast o cambiar el texto del botón tras copiar.
  • ¿Qué diferencia hay entre execCommand('copy') y clipboard.writeText()?
    • execCommand es una API antigua y poco confiable; clipboard.writeText es el método moderno y seguro.

Conclusión

Copiar texto al portapapeles con JavaScript es una funcionalidad pequeña, pero poderosa. Usando navigator.clipboard.writeText() puedes ofrecer una experiencia fluida, segura y moderna.

En mi caso, aplicar esta técnica en mis proyectos mejoró notablemente la interacción con los usuarios, en la web de Academia, lo implementé para que el usuario pueda copiar los códigos con un solo click.

Esta es la forma recomendada de copiar y pegar textos en JavaScript, pero, te dejo la forma obsoleta para que lo tengas de referencia.

Cómo copiar contenidos en el portapapeles con JavaScript

En esta entrada veremos cómo copiar un texto que esté establecido en nuestro HTML en nuestro portapapeles empleando JavaScript sin necesidad de emplear Flash o alguna tecnologías de un tercero.

El portapapeles no es más que una herramienta del sistema operativo que permite almacenar datos como textos e imágenes.

Se accede al portapapeles generalmente empleando la combinación Ctrl + C para copiar y Ctrl + V para pegar.

Crearemos una sencilla función cuyo núcleo es el método llamado execCommand que permite ejecutar comandos al documento actual con la selección actual, esto puede sonar algo enredado pero en realidad es bastante fácil la función.

Con lo dicho anteriormente, y para que pueda funcionar debemos tener un campo de texto oculto u otro que nos permita crear un campo de selección el cual es el campo selección actual que emplearemos para vaciar el texto que queramos copiar en el portapapeles que luego será copiado mediante el método execCommand con el parámetro "copy"; sin ir más lejos la función:

function copiar(id_elemento) {
// Crea un campo de texto "oculto"
var aux = document.createElement("input");
// Asigna el contenido del elemento especificado al valor del campo
aux.setAttribute("value", document.getElementById(id_elemento).innerHTML);
// Añade el campo a la página
document.body.appendChild(aux);
// Selecciona el contenido del campo
aux.select();
// Copia el texto seleccionado
document.execCommand("copy");
// Elimina el campo de la página
document.body.removeChild(aux);
console.log("texto copiado")
}

Puedes darle un buen uso al script anterior creando un campo de texto con contenido editable como hemos visto anteriormente en: Secciones editables en el HTML con el atributo contenteditable.

Soporte de los navegadores

Antes de emplear el comando document.execCommand("copy"); es de buena práctica comprobar soporte en el navegador; para ello empleamos el siguiente comando:

document.queryCommandSupported('copy');
NavegadorVersión
Internet Explorer10+
Google Chrome43+
Firefox41+
Opera29+
Safari(sin soporte)

Ver

Obteniendo una captura de pantalla del portapapeles (clipboard) con JavaScript

Ver ejemplo Descargar fuente

En esta entrada veremos como copiar una imagen producto de una captura de pantalla que se encuentre guardada de manera temporal en el portapapeles o clipboard en un elemento <img>.

Además veremos como podemos enviar esta imagen a través de Ajax para su procesamiento y guardado en el servidor; a continuación, la tabla de contenido:

  1. Capturando la pantalla de un ordenador
  2. Guardando la captura de pantalla en un elemento con JavaScript
    1. El evento paste en JavaScript
    2. Definiendo nuestra función para capturar el evento
    3. Explicando la función anterior…
  3. Enviando la imagen copiada del clipboard al servidor con Ajax
    1. Guardando la imagen en el servido
    2. Generando un string codificado en base64 de la imagen en el servidor
    3. ¿Cómo guardar la imagen en base64 en nuestra base de datos?

1.0 Capturando la pantalla de un ordenador

Muchas distribuciones en Linux como Fedora ofrecen aplicaciones desde las cuales podemos realizar capturas de pantallas:

captura de pantalla aplicación

Que permiten guardar una imagen producto de la captura de pantalla en alguna ubicación en la computadora o en el portapapeles; este último es parte de nuestro caso de interés.

También se pueden usar la tecla F12 o la tecla ImprPant provista en muchos teclados; aunque es posible que estas acciones no copien la imagen en el portapapeles o inclusive que no funcionen en determinados sistemas operativos.

2.0 Guardando la captura de pantalla en un elemento <img> con JavaScript

Una vez que nos hayamos hecho con la captura de pantalla en el portapapeles, debemos definir un evento que permita capturar el momento cuando copiamos algún contenido en un sitio web mediante:

  • La combinación Ctrl + V en nuestro teclado.
  • La seleccionando la opción paste/pegar desde nuestro navegador.
  • El menú emergente, presionamos sobre la opción paste/pegar.

Más información en la w3schools.

2.1 El evento paste en JavaScript

La API de JavaScript provee un evento que permite capturar el evento paste/pegar a través de la siguiente línea de código:

window.addEventListener("paste", pasteEvent);

2.2 Definiendo nuestra función para capturar el evento

Ahora podemos definir la función llamada pasteEvent() que se ejecutará cuando ocurra alguno de los eventos mencionados anteriormente; dicha función permite copiar el contenido del portapapeles en un elemento de tipo <img>; veamos la definición completa de la función:

          window.addEventListener("paste", processEvent);
            function processEvent(e) {
                for (var i = 0; i < e.clipboardData.items.length; i++) {
                    // get the clipboard item
                    // obtengo el clipboard item
                    var clipboardItem = e.clipboardData.items[0];
                    var type = clipboardItem.type;
                    // verifico si es una imagen
                    if (type.indexOf("image") != -1) {
                        // obtengo el contenido de la imagen BLOB
                        var blob = clipboardItem.getAsFile();
                        console.log("blob", blob);
                        // creo un la URL del objeto
                        var blobUrl = URL.createObjectURL(blob);
                        console.log("blobUrl", blobUrl);
                        // agrego la captura a mi imagen
                        document.getElementsByTagName("img")[0].setAttribute("src", blobUrl);
                    } else {
                        console.log("No soportado " + type);
                    }
                }
            }

2.3 Explicando la función anterior…

ClipboardEvent.clipboardData para leer los datos del portapapeles

El objeto clipboardData permite acceder en modo sólo lectura a la data contenida en el portapapeles a través de un Array de items; También podemos encontrar el tipo de datos (el cual puede ser texto, imágenes, etc) que se encuentra en una posición determinada del Array.

var clipboardItem = e.clipboardData.items[i];

Una vez que tengamos el item a evaluar; determinamos el tipo de data y la data almacenada respectivamente:

  • Consultamos el tipo a través del método type type.indexOf("image").
  • Obtenemos la data BLOB (raw data) a través del método getAsFile() clipboardItem.getAsFile().

Luego de inspeccionar el tipo de data y obtenida la misma, es necesario convertir la data de un objeto BLOB a un DOMString empleando el método createObjectURL() que crea una URL que representa el objeto, para que la imagen pueda ser reenderizada en un elemento de tipo <img>:

var blobUrl = URL.createObjectURL(blob);  

Finalmente copiamos el contenido de la imagen proveniente de la captura de pantalla en un elemento <img>:

img.attr("src", blobUrl);

2.4 Resultado final del experimento

Copia la imagen que tengas en el portapapel con Ctrl + V u otra modalidad.

3. Enviando la imagen copiada del clipboard al servidor con Ajax

3.1 Guardando la imagen en el servidor

Un uso útil del experimento presentado anteriormente consiste en poder guardar la imagen ya generada y guardada en un elemento <img> en el servidor; para esto podemos emplear Ajax o un formulario de la manera tradicional; aunque antes de poder guardar la imagen en el servidor debemos procesarla para que pueda ser manejada correctamente.

3.2 Generando un string codificado en base64 de la imagen en el servidor

Llegado a este punto, si verificamos el atributo source src de la imagen:

src img

Nos daremos cuenta que no es más que un valor que representa nuestra imagen, más no nos ofrece ninguna información sobre la misma; para poder guardar una imagen en el servidor no es posible emplear un tipo BLOB o la URL que lo represente; debemos de codificar la misma en base64 para que la imagen pueda ser procesada fácilmente desde el servidor.

Podemos convertir nuestra imagen fácilmente de un tipo BLOB a base64 con el siguiente script:

            var reader = new window.FileReader();
            reader.readAsDataURL(clipboardItem.getAsFile());
            
            reader.onload = function() {
                console.log(reader.result.replace('data:image/png;base64,', '')
                        .toString()
                $.ajax({
                    type: 'POST',
                    url: URL,
                    data: {
                        'pantalla': reader.result
                                .replace('data:image/png;base64,', '').toString(),
                    },
                    success: function(response) {}
            });
            }

El objeto FileReader()

Primero creamos un objeto de tipo FileReader() que permite leer archivos de manera asíncrona.

Una vez leído el archivo (nuestra imagen) la propiedad result para leer el contenido del archivo/imagen ya codificado en base64;.

Una vez codificada nuestra imagen, es posible enviar la imagen codificada en base64 por Ajax o a través de un campo en un formulario.

3.3 ¿Cómo guardar la imagen en base64 en nuestra base de datos?

Una vez obtenida nuestra imagen codificada en base64 en el lado del servidor se debe de decodificar la misma; si empleamos Java Web podemos usar la siguiente función para decodificar la imagen en base64 a un arreglo de byte:

byte imagen[] = Base64.decodeBase64(imageString);

En PHP existe una función similar:

$data = base64_decode($data);

Ya decodificada la imagen se puede guardar el base de datos como si se tratase de cualquier otro archivo obtenido en el servidor por un input de tipo file.

Consideraciones

Dependiente de la función empleada para decodificación a emplear puede ser necesario retirar la cabecera data:image/png;base64 presente en nuestra imagen codificada en base64; esto se aplica en para la función Base64.decodeBase64 en Java, en caso de dejarse esta cabecera la imagen podría decodificarse con errores y por lo tanto el archivo estaría corrupto.

Ver ejemplo Descargar fuente

Acepto recibir anuncios de interes sobre este Blog.

Cómo usar navigator.clipboard.writeText() para copiar texto al portapapeles en JavaScript. Aprende buenas prácticas, errores comunes y soporte por navegador.

| 👤 Andrés Cruz

🇺🇸 In english