Last updated: Mar 7, 2024
Reading timeยท6 min

The navigator.clipboard object might be undefined because the Clipboard
API is only available in secure contexts (HTTPS).
You can resolve the issue in multiple ways:
document.execCommand if navigator.clipboard is
undefined.As shown in this section of the MDN docs, the Clipboard API is only available in secure contexts (HTTPS).
If you try to use the API using the HTTP protocol, then navigator.clipboard
will be undefined and you will likely get one of the following errors:
You can use the window.isSecureContext property if you need to check if your code is run in a secure context.
The property returns true if the context is secure and false otherwise.
console.log(window.isSecureContext); if (window.isSecureContext) { console.log( 'The context is secure, can use navigator.clipboard', ); } else { console.log('The context is NOT secure'); }
One way to get around the issue is to enable the "Insecure origins treated as secure" setting:
Enter chrome://flags in your browser's address bar.
Search for Insecure origins treated as secure.
Enable the setting by clicking on the button to the right.
Type the origins that you want to enable the setting for, e.g.
http://localhost:3000 or http://example.com.

http://localhost:3000,http://example.com
http:// or https://).
Suppose you have the following HTML.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <div class="box">bobbyhadz.com</div> <div id="content">Some text to copy here</div> <button id="btn">Copy text</button> <script src="index.js"></script> </body> </html>
Here is the code for the index.js file.
const button = document.getElementById('btn'); const contentDiv = document.getElementById('content'); button.addEventListener('click', async () => { console.log(navigator.clipboard); await navigator.clipboard.writeText(contentDiv.innerText); console.log('Copied!') });

The code sample works after making the change and enables me to copy the text without using HTTPS.
Note that the writeText() method returns a Promise, therefore you either have
to await it or use the .then() syntax.
Here is an example that uses the then() syntax instead.
const button = document.getElementById('btn'); const contentDiv = document.getElementById('content'); button.addEventListener('click', () => { console.log(navigator.clipboard); navigator.clipboard .writeText(contentDiv.innerText) .then(() => { console.log('The text has been copied'); }); });
The callback function we passed to .then() gets called after the Promise has
been resolved.
navigator.clipboard is undefinedAn alternative approach to resolve the issue with navigator.clipboard being
undefined is to provide a fallback using document.execCommand.
Here is the HTML for the example.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <div class="box">bobbyhadz.com</div> <button id="btn">Copy text</button> <script src="index.js"></script> </body> </html>
And here is the related JavaScript code.
const button = document.getElementById('btn'); button.addEventListener('click', async () => { try { await copyToClipboard('The text you want to copy ๐'); console.log('Copied!'); } catch (err) { console.log(err); } }); /** * Universal copyToClipboard function */ async function copyToClipboard(textToCopy) { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(textToCopy); } else { const textarea = document.createElement('textarea'); textarea.value = textToCopy; // Move the textarea outside the viewport to make it invisible textarea.style.position = 'absolute'; textarea.style.left = '-99999999px'; document.body.prepend(textarea); // highlight the content of the textarea element textarea.select(); try { document.execCommand('copy'); } catch (err) { console.log(err); } finally { textarea.remove(); } } }
The copyToClipboard() function takes the text you want to copy as a parameter
and copies the text to the user's clipboard.
The function is async, so you
have to await it.
The function checks if the context is secure using the window.isSecureContext
property.
if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(textToCopy); }
This way you won't get the "Cannot read properties of undefined (reading
'writeText')" error even if the navigator.clipboard property is undefined.
If the context is secure, the window.isSecureContext property returns true
and the if block runs.
Inside the if block, we use the navigator.clipboard.writeText() method to
copy the specified text to the user's clipboard.
If the context is not secure, the else block runs.
else { const textarea = document.createElement('textarea'); textarea.value = textToCopy; // Move the textarea outside the viewport to make it invisible textarea.style.position = 'absolute'; textarea.style.left = '-99999999px'; document.body.prepend(textarea); // highlight the content of the textarea element textarea.select(); try { document.execCommand('copy'); } catch (err) { console.log(err); } finally { textarea.remove(); } }
Inside the else block, we create a textarea element to use an old trick.
value of the textarea element to the text we want to copy.textarea outside the viewport to make it invisible.select() method to highlight the text in the textarea element.Once the text is highlighted, we use the document.execCommand() method to copy the selected text.
try { document.execCommand('copy'); } catch (err) { console.log(err); } finally { textarea.remove(); }
Even though the document.execCommand method is deprecated, it is still widely
supported by browsers as shown in
this table.
The copyToClipboard() function:
navigator.clipboard API if it is available in the environment.document.execCommand method as a fallback if navigator.clipboard
is not available.This way the text is copied to the user's clipboard regardless if the context is secure (HTTPS).
To use the copyToClipboard function, pass it the text you want to copy to the
user's clipboard and
await the Promise.
const button = document.getElementById('btn'); button.addEventListener('click', async () => { try { await copyToClipboard('The text you want to copy ๐'); console.log('Copied!'); } catch (err) { console.log(err); } });
Notice that we marked the callback function we passed to
addEventListener
as async to be able to use the await keyword.
We await the Promise that the copyToClipboard function returns.
You can also enable clipboard access for the specific URL in the "Privacy and security" tab in Chrome:


If you don't see the site under Recent activity, click on View permissions and data stored across sites and select the specific site.


After you allow clipboard access to the site, you should be able to use the
navigator.clipboard API.
navigator.clipboard to be undefinedThe navigator.clipboard property might be undefined and cause the "Cannot
read properties of undefined (reading 'writeText')" error for multiple
reasons:
navigator.clipboard API in an insecure context (HTTP, and not
HTTPS).navigator.clipboard API is not
supported.navigator.clipboard API when the user hasn't focused the
tab in the browser. The browser tab has to have focus for you to be able to
use the navigator.clipboard API.navigator.clipboard API.navigator.clipboard.writeText() method.You can learn more about the related topics by checking out the following tutorials: