How do I copy a string to the clipboard?

Question:

I’m trying to make a basic Windows application that builds a string out of user input and then adds it to the clipboard. How do I copy a string to the clipboard using Python?

Asked By: tester

||

Answers:

Looks like you need to add win32clipboard to your site-packages. It’s part of the pywin32 package

Answered By: Jason Coon

You can also use ctypes to tap into the Windows API and avoid the massive pywin32 package. This is what I use (excuse the poor style, but the idea is there):

import ctypes

# Get required functions, strcpy..
strcpy = ctypes.cdll.msvcrt.strcpy
OpenClipboard = ctypes.windll.user32.OpenClipboard    # Basic clipboard functions
EmptyClipboard = ctypes.windll.user32.EmptyClipboard
GetClipboardData = ctypes.windll.user32.GetClipboardData
SetClipboardData = ctypes.windll.user32.SetClipboardData
CloseClipboard = ctypes.windll.user32.CloseClipboard
GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc    # Global memory allocation
GlobalLock = ctypes.windll.kernel32.GlobalLock     # Global memory Locking
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock
GMEM_DDESHARE = 0x2000

def Get():
  OpenClipboard(None) # Open Clip, Default task

  pcontents = GetClipboardData(1) # 1 means CF_TEXT.. too lazy to get the token thingy...

  data = ctypes.c_char_p(pcontents).value

  #GlobalUnlock(pcontents) ?
  CloseClipboard()

  return data

def Paste(data):
  OpenClipboard(None) # Open Clip, Default task

  EmptyClipboard()

  hCd = GlobalAlloc(GMEM_DDESHARE, len(bytes(data,"ascii")) + 1)

  pchData = GlobalLock(hCd)

  strcpy(ctypes.c_char_p(pchData), bytes(data, "ascii"))

  GlobalUnlock(hCd)

  SetClipboardData(1, hCd)

  CloseClipboard()
Answered By: kapace

Actually, pywin32 and ctypes seem to be an overkill for this simple task. tkinter is a cross-platform GUI framework, which ships with Python by default and has clipboard accessing methods along with other cool stuff.

If all you need is to put some text to system clipboard, this will do it:

from tkinter import Tk # in Python 2, use "Tkinter" instead 
r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append('i can has clipboardz?')
r.update() # now it stays on the clipboard after the window is closed
r.destroy()

And that’s all, no need to mess around with platform-specific third-party libraries.

If you are using Python 2, replace tkinter with Tkinter.

Answered By: atomizer

I didn’t have a solution, just a workaround.

Windows Vista onwards has an inbuilt command called clip that takes the output of a command from command line and puts it into the clipboard. For example, ipconfig | clip.

So I made a function with the os module which takes a string and adds it to the clipboard using the inbuilt Windows solution.

import os
def addToClipBoard(text):
    command = 'echo ' + text.strip() + '| clip'
    os.system(command)

# Example
addToClipBoard('penny lane')

# Penny Lane is now in your ears, eyes, and clipboard.

As previously noted in the comments however, one downside to this approach is that the echo command automatically adds a newline to the end of your text. To avoid this you can use a modified version of the command:

def addToClipBoard(text):
    command = 'echo | set /p nul=' + text.strip() + '| clip'
    os.system(command)

If you are using Windows XP it will work just following the steps in Copy and paste from Windows XP Pro’s command prompt straight to the Clipboard.

Answered By: user1227883

Widgets also have method named .clipboard_get() that returns the contents of the clipboard (unless some kind of error happens based on the type of data in the clipboard).

The clipboard_get() method is mentioned in this bug report:
http://bugs.python.org/issue14777

Strangely, this method was not mentioned in the common (but unofficial) online TkInter documentation sources that I usually refer to.

Answered By: mpb

You can use pyperclip – cross-platform clipboard module. Or Xerox – similar module, except requires the win32 Python module to work on Windows.

Answered By: pongo

For some reason I’ve never been able to get the Tk solution to work for me. kapace’s solution is much more workable, but the formatting is contrary to my style and it doesn’t work with Unicode. Here’s a modified version.

import ctypes

from ctypes.wintypes import BOOL, HWND, HANDLE, HGLOBAL, UINT, LPVOID
from ctypes import c_size_t as SIZE_T

OpenClipboard = ctypes.windll.user32.OpenClipboard
OpenClipboard.argtypes = HWND,
OpenClipboard.restype = BOOL
EmptyClipboard = ctypes.windll.user32.EmptyClipboard
EmptyClipboard.restype = BOOL
GetClipboardData = ctypes.windll.user32.GetClipboardData
GetClipboardData.argtypes = UINT,
GetClipboardData.restype = HANDLE
SetClipboardData = ctypes.windll.user32.SetClipboardData
SetClipboardData.argtypes = UINT, HANDLE
SetClipboardData.restype = HANDLE
CloseClipboard = ctypes.windll.user32.CloseClipboard
CloseClipboard.restype = BOOL
CF_UNICODETEXT = 13

GlobalAlloc = ctypes.windll.kernel32.GlobalAlloc
GlobalAlloc.argtypes = UINT, SIZE_T
GlobalAlloc.restype = HGLOBAL
GlobalLock = ctypes.windll.kernel32.GlobalLock
GlobalLock.argtypes = HGLOBAL,
GlobalLock.restype = LPVOID
GlobalUnlock = ctypes.windll.kernel32.GlobalUnlock
GlobalUnlock.argtypes = HGLOBAL,
GlobalSize = ctypes.windll.kernel32.GlobalSize
GlobalSize.argtypes = HGLOBAL,
GlobalSize.restype = SIZE_T

GMEM_MOVEABLE = 0x0002
GMEM_ZEROINIT = 0x0040

unicode_type = type(u'')

def get():
    text = None
    OpenClipboard(None)
    handle = GetClipboardData(CF_UNICODETEXT)
    pcontents = GlobalLock(handle)
    size = GlobalSize(handle)
    if pcontents and size:
        raw_data = ctypes.create_string_buffer(size)
        ctypes.memmove(raw_data, pcontents, size)
        text = raw_data.raw.decode('utf-16le').rstrip(u'')
    GlobalUnlock(handle)
    CloseClipboard()
    return text

def put(s):
    if not isinstance(s, unicode_type):
        s = s.decode('mbcs')
    data = s.encode('utf-16le')
    OpenClipboard(None)
    EmptyClipboard()
    handle = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, len(data) + 2)
    pcontents = GlobalLock(handle)
    ctypes.memmove(pcontents, data, len(data))
    GlobalUnlock(handle)
    SetClipboardData(CF_UNICODETEXT, handle)
    CloseClipboard()

paste = get
copy = put

The above has changed since this answer was first created, to better cope with extended Unicode characters and Python 3. It has been tested in both Python 2.7 and 3.5, and works even with emoji such as U0001f601 ( ).

Update 2021-10-26: This was working great for me in Windows 7 and Python 3.8. Then I got a new computer with Windows 10 and Python 3.10, and it failed for me the same way as indicated in the comments. This post gave me the answer. The functions from ctypes don’t have argument and return types properly specified, and the defaults don’t work consistently with 64-bit values. I’ve modified the above code to include that missing information.

Answered By: Mark Ransom

I’ve tried various solutions, but this is the simplest one that passes my test:

#coding=utf-8

import win32clipboard  # http://sourceforge.net/projects/pywin32/

def copy(text):
    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardText(text, win32clipboard.CF_UNICODETEXT)
    win32clipboard.CloseClipboard()
def paste():
    win32clipboard.OpenClipboard()
    data = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)
    win32clipboard.CloseClipboard()
    return data

if __name__ == "__main__":  
    text = "Testingnthe “clip—board”:  "
    try: text = text.decode('utf8')  # Python 2 needs decode to make a Unicode string.
    except AttributeError: pass
    print("%r" % text.encode('utf8'))
    copy(text)
    data = paste()
    print("%r" % data.encode('utf8'))
    print("OK" if text == data else "FAIL")

    try: print(data)
    except UnicodeEncodeError as er:
        print(er)
        print(data.encode('utf8'))

Tested OK in Python 3.4 on Windows 8.1 and Python 2.7 on Windows 7. Also when reading Unicode data with Unix linefeeds copied from Windows. Copied data stays on the clipboard after Python exits: "Testing
the “clip—board”: "

If you want no external dependencies, use this code (now part of cross-platform pyperclipC:Python34Scriptspip install --upgrade pyperclip):

def copy(text):
    GMEM_DDESHARE = 0x2000
    CF_UNICODETEXT = 13
    d = ctypes.windll # cdll expects 4 more bytes in user32.OpenClipboard(None)
    try:  # Python 2
        if not isinstance(text, unicode):
            text = text.decode('mbcs')
    except NameError:
        if not isinstance(text, str):
            text = text.decode('mbcs')
    d.user32.OpenClipboard(0)
    d.user32.EmptyClipboard()
    hCd = d.kernel32.GlobalAlloc(GMEM_DDESHARE, len(text.encode('utf-16-le')) + 2)
    pchData = d.kernel32.GlobalLock(hCd)
    ctypes.cdll.msvcrt.wcscpy(ctypes.c_wchar_p(pchData), text)
    d.kernel32.GlobalUnlock(hCd)
    d.user32.SetClipboardData(CF_UNICODETEXT, hCd)
    d.user32.CloseClipboard()

def paste():
    CF_UNICODETEXT = 13
    d = ctypes.windll
    d.user32.OpenClipboard(0)
    handle = d.user32.GetClipboardData(CF_UNICODETEXT)
    text = ctypes.c_wchar_p(handle).value
    d.user32.CloseClipboard()
    return text
Answered By: Cees Timmerman
import wx

def ctc(text):

    if not wx.TheClipboard.IsOpened():
        wx.TheClipboard.Open()
        data = wx.TextDataObject()
        data.SetText(text)
        wx.TheClipboard.SetData(data)
    wx.TheClipboard.Close()

ctc(text)
Answered By: jlk

Code snippet to copy the clipboard:

Create a wrapper Python code in a module named (clipboard.py):

import clr
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import Clipboard
def setText(text):
    Clipboard.SetText(text)

def getText():
    return Clipboard.GetText()

Then import the above module into your code.

import io
import clipboard
code = clipboard.getText()
print code
code = "abcd"
clipboard.setText(code)

I must give credit to the blog post Clipboard Access in IronPython.

Answered By: Nagesh

You can use the excellent pandas, which has a built in clipboard support, but you need to pass through a DataFrame.

import pandas as pd
df=pd.DataFrame(['Text to copy'])
df.to_clipboard(index=False,header=False)
Answered By: Gadi Oron

I think there is a much simpler solution to this.

name = input('What is your name? ')
print('Hello %s' % (name) )

Then run your program in the command line

python greeter.py | clip

This will pipe the output of your file to the clipboard

Answered By: jdeyrup

This is an improved answer of atomizer. Note that

  • there are 2 calls of update() and
  • inserted 200 ms delay between them.

They protect freezing applications due to an unstable state of the clipboard:

from Tkinter import Tk
import time     

r = Tk()
r.withdraw()
r.clipboard_clear()
r.clipboard_append('some string')

r.update()
time.sleep(.2)
r.update()

r.destroy()
Answered By: MarianD

The simplest way is with pyperclip. Works in python 2 and 3.

To install this library, use:

pip install pyperclip

Example usage:

import pyperclip

pyperclip.copy("your string")

If you want to get the contents of the clipboard:

clipboard_content = pyperclip.paste()
Answered By: maviz

you can try this:

command = 'echo content |clip'
subprocess.check_call(command, shell=True)
Answered By: Y.Max

The snippet I share here take advantage of the ability to format text files: what if you want to copy a complex output to the clipboard ? (Say a numpy array in column or a list of something)

import subprocess
import os

def cp2clip(clist):

    #create a temporary file
    fi=open("thisTextfileShouldNotExist.txt","w")

    #write in the text file the way you want your data to be
    for m in clist:
        fi.write(m+"n")

    #close the file
    fi.close()

    #send "clip < file" to the shell
    cmd="clip < thisTextfileShouldNotExist.txt"
    w = subprocess.check_call(cmd,shell=True)

    #delete the temporary text file
    os.remove("thisTextfileShouldNotExist.txt")

    return w

works only for windows, can be adapted for linux or mac I guess. Maybe a bit complicated…

example:

>>>cp2clip(["ET","phone","home"])
>>>0

Ctrl+V in any text editor :

ET
phone
home
Answered By: thomasJeanne

If you don’t like the name you can use the derivative module clipboard.

Note: It’s just a selective wrapper of pyperclip

After installing, import it:

import clipboard

Then you can copy like this:

clipboard.copy("This is copied")

You can also paste the copied text:

clipboard.paste()
Answered By: Nouman

In addition to Mark Ransom’s answer using ctypes:
This does not work for (all?) x64 systems since the handles seem to be truncated to int-size.
Explicitly defining args and return values helps to overcomes this problem.

import ctypes
import ctypes.wintypes as w

CF_UNICODETEXT = 13

u32 = ctypes.WinDLL('user32')
k32 = ctypes.WinDLL('kernel32')

OpenClipboard = u32.OpenClipboard
OpenClipboard.argtypes = w.HWND,
OpenClipboard.restype = w.BOOL

GetClipboardData = u32.GetClipboardData
GetClipboardData.argtypes = w.UINT,
GetClipboardData.restype = w.HANDLE

EmptyClipboard = u32.EmptyClipboard
EmptyClipboard.restype = w.BOOL

SetClipboardData = u32.SetClipboardData
SetClipboardData.argtypes = w.UINT, w.HANDLE,
SetClipboardData.restype = w.HANDLE

CloseClipboard = u32.CloseClipboard
CloseClipboard.argtypes = None
CloseClipboard.restype = w.BOOL

GHND = 0x0042

GlobalAlloc = k32.GlobalAlloc
GlobalAlloc.argtypes = w.UINT, w.ctypes.c_size_t,
GlobalAlloc.restype = w.HGLOBAL

GlobalLock = k32.GlobalLock
GlobalLock.argtypes = w.HGLOBAL,
GlobalLock.restype = w.LPVOID

GlobalUnlock = k32.GlobalUnlock
GlobalUnlock.argtypes = w.HGLOBAL,
GlobalUnlock.restype = w.BOOL

GlobalSize = k32.GlobalSize
GlobalSize.argtypes = w.HGLOBAL,
GlobalSize.restype = w.ctypes.c_size_t

unicode_type = type(u'')

def get():
    text = None
    OpenClipboard(None)
    handle = GetClipboardData(CF_UNICODETEXT)
    pcontents = GlobalLock(handle)
    size = GlobalSize(handle)
    if pcontents and size:
        raw_data = ctypes.create_string_buffer(size)
        ctypes.memmove(raw_data, pcontents, size)
        text = raw_data.raw.decode('utf-16le').rstrip(u'')
    GlobalUnlock(handle)
    CloseClipboard()
    return text

def put(s):
    if not isinstance(s, unicode_type):
        s = s.decode('mbcs')
    data = s.encode('utf-16le')
    OpenClipboard(None)
    EmptyClipboard()
    handle = GlobalAlloc(GHND, len(data) + 2)
    pcontents = GlobalLock(handle)
    ctypes.memmove(pcontents, data, len(data))
    GlobalUnlock(handle)
    SetClipboardData(CF_UNICODETEXT, handle)
    CloseClipboard()

#Test run
paste = get
copy = put
copy("Hello World!")
print(paste())
Answered By: M.Bauer

Here’s the most easy and reliable way I found if you’re okay depending on Pandas. However I don’t think this is officially part of the Pandas API so it may break with future updates. It works as of 0.25.3

from pandas.io import clipboard
clipboard.copy("test")
Answered By: pyjamas

Use python’s clipboard library!

import clipboard as cp
cp.copy("abc")

Clipboard contains ‘abc’ now. Happy pasting!

Answered By: WhyNotCode

Not all of the answers worked for my various python configurations so this solution only uses the subprocess module. However, copy_keyword has to be pbcopy for Mac or clip for Windows:

import subprocess
subprocess.run('copy_keyword', universal_newlines=True, input='New Clipboard Value  ')

Here’s some more extensive code that automatically checks what the current operating system is:

import platform
import subprocess

copy_string = 'New Clipboard Value  '

# Check which operating system is running to get the correct copying keyword.
if platform.system() == 'Darwin':
    copy_keyword = 'pbcopy'
elif platform.system() == 'Windows':
    copy_keyword = 'clip'

subprocess.run(copy_keyword, universal_newlines=True, input=copy_string)
Answered By: Fetchinator7

You can use winclip32 module!
install:

pip install winclip32

to copy:

import winclip32
winclip32.set_clipboard_data(winclip32.UNICODE_STD_TEXT, "some text")

to get:

import winclip32
print(winclip32.get_clipboard_data(winclip32.UNICODE_STD_TEXT))

for more informations: https://pypi.org/project/winclip32/

Answered By: pypcdev

Use pyperclip module

Install using pip pip install pyperclip.

Copy text "Hello World!" to clip board

import pyperclip
pyperclip.copy('Hello World!')

You can use Ctrl+V anywhere to paste this somewhere.

Paste the copied text using python

pyperclip.paste() # This returns the copied text of type <class 'str'>
Answered By: Ali Sajjad

On Windows, you can use: pywin32.

Install it with: pip install pywin32.

Use it like this.

import win32clipboard


def to_clipboard(txt):

    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardText(txt)
    win32clipboard.CloseClipboard()
Answered By: bravhek

also you can use > clipboard

import clipboard

def copy(txt):
    clipboard.copy(txt)
    
copy("your txt")
Answered By: bnh

If (and only if) the application already uses Qt, you can use this (with the advantage of no additional third party dependency)

from PyQt5.QtWidgets import QApplication
clipboard = QApplication.clipboard()

# get text (if there's text inside instead of e.g. file)
clipboard.text()

# set text
clipboard.setText(s)

This requires a Qt application object to be already constructed, so it should not be used unless the application already uses Qt.

Besides, as usual, in X systems (and maybe other systems too), the content only persist until the application exists unless you use something like parcellite or xclipboard.

Documentation:

See also: python – PyQT – copy file to clipboard – Stack Overflow

Answered By: user202729

Solution with stdlib, without security issues

The following solution works in Linux without any additional library and without the risk of executing unwanted code in your shell.

import subprocess

def to_clipboard(text: str) -> None:
    sp = subprocess.Popen(["xclip"], stdin=subprocess.PIPE, 
                                      stdout=subprocess.PIPE)
    sp.communicate(text.encode("utf8"))

Note that there multiple clipboard in Linux, the you use with the Middle Mouse (Primary) and yet another that you use pressing STRG+C,STRG+V.

You can define which clipboard is used by adding a selection parameter i.e. ["xclip", "-selection", "clipboard"].
See the man xclip for details.

If you using Windows, just replace xclip with clip.

This solution works without Tkinter, which not available some Python installations (i.e. the custom build I am currently using).

Answered By: Kound

My multiplatform solution base on this question:

import subprocess
import distutils.spawn

def clipit(text):
    if distutils.spawn.find_executable("xclip"):
        # for Linux
        subprocess.run(["xclip", "-i"], input=text.encode("utf8"))
    elif distutils.spawn.find_executable("xsel"):
        # for Linux
        subprocess.run(["xsel", "--input"], input=text.encode("utf8"))
    elif distutils.spawn.find_executable("clip"):
        # for Windows
        subprocess.run(["clip"], input=text.encode("utf8"))
    else:
        import pyperclip

        print("I use module pyperclip.")
        pyperclip.copy(text)

Answered By: MarrekNožka
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.