Working on a project that uses a little keyboard and an E-ink display which will run on a raspberry pi Zero. I have tried a couple of keyboard packages for python (pynput, pyxhook) and have written/tested simple keystroke loggers that work fine on my desktop (ubuntu)

However I try to run them on the pi with no monitor both libraries die

DisplayConnectionError: Can't connect to display ":0": [Errno 111] Connection refused

I know at least pyxhook has the ability to capture mouse movement so that makes sense why it would "Need" access to the monitor. But all I want is a way to capture the keyboard input in a process running in the background but with no monitor attached

The libraries can also return the current window that has focus as part of the key event, and that may be the other reason the monitor is tied in so deep.I tried

$export DISPLAY=":0"

did not help.

here is simple code for pynput, works with monitor but not when running headless(running it from SSH)

#!/usr/bin/env python

from pynput import keyboard

def on_press(key):
    print('Key {} pressed.'.format(key))
    if str(key) == 'Key.esc':
        return False

with keyboard.Listener(on_press = on_press) as listener:

Is there any way to get these to work, or possibly a different way of a approaching this.

full stack trace of above program failing

Traceback (most recent call last):
  File "./keylog.py", line 3, in <module>
    from pynput import keyboard
  File "/usr/local/lib/python2.7/dist-packages/pynput/__init__.py", line 23, in <module>
    from . import keyboard
  File "/usr/local/lib/python2.7/dist-packages/pynput/keyboard/__init__.py", line 49, in <module>
    from ._xorg import KeyCode, Key, Controller, Listener
  File "/usr/local/lib/python2.7/dist-packages/pynput/keyboard/_xorg.py", line 38, in <module>
    from pynput._util.xorg import (
  File "/usr/local/lib/python2.7/dist-packages/pynput/_util/xorg.py", line 38, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pynput/_util/xorg.py", line 36, in _check
    display = Xlib.display.Display()
  File "/usr/local/lib/python2.7/dist-packages/Xlib/display.py", line 89, in __init__
    self.display = _BaseDisplay(display)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/display.py", line 71, in __init__
    protocol_display.Display.__init__(self, *args, **keys)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/protocol/display.py", line 90, in __init__
    self.socket = connect.get_socket(name, protocol, host, displayno)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/support/connect.py", line 87, in get_socket
    return mod.get_socket(dname, protocol, host, dno)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/support/unix_connect.py", line 113, in get_socket
    raise error.DisplayConnectionError(dname, str(val))
Xlib.error.DisplayConnectionError: Can't connect to display ":0": [Errno 111] Connection refused
  • You will not be able to do this unless you run the full X11 server on your board, even without a monitor attached (look for the xorg package for the server). An alternative is to read directly from the libinput interface. For python see python-evdev – meuh Mar 1 '18 at 16:23

Ok, i figured it out, figured I would post the answer.

pythons keyboard module, docs and source here

as stated in the "Known Limitations" section, (even though I don't think this is a limitation!)

"To avoid depending on X, the Linux parts reads raw device files (/dev/input/input*) but this requires root."

So this does bring up security issues obviously since the program now needs root privileges, but for my case this is not an issue.

pip install keyboard

simple program

import keyboard
import time

def key_press(key):


while True:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.