Skip to main content

AnalogSense Python SDK

Python port of AnalogSense.js for analog keyboard input.

Supported Keyboards/Devices

  • Everything by WootingT
  • Everything by NuPhy
  • Everything by DrunkDeer
  • Razer Huntsman V2 AnalogR
  • Razer Huntsman Mini AnalogR
  • Razer Huntsman V3 ProR
  • Razer Huntsman V3 Pro MiniR
  • Razer Huntsman V3 Pro TenkeylessR
  • Keychron Q1 HEP, F
  • Keychron Q3 HEP, F
  • Keychron Q5 HEP, F
  • Keychron K2 HEP, F
  • Lemokey P1 HEP, F
  • Madlions MAD60HEP
  • Madlions MAD68HEP
  • Madlions MAD68RP
  • Redragon K709HEP, T

T Tested and should work. Feel free to open issues/prs about boards not being picked up properly
R Razer Synapse needs to be installed and running for analogue inputs to be received from this keyboard.
P The official firmware only supports polling, which can lead to lag and missed inputs.
F Custom firmware with full analog report functionality is available.

Installation

pip install AnalogSensePy

On Linux you may need udev rules or sudo for hid

printf '%s\n' \
  'KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="31e3", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="03eb", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="1532", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="19f5", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="352d", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="3434", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="362d", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="373b", MODE="0660", GROUP="input"' \
  'SUBSYSTEM=="usb", ATTRS{idVendor}=="372e", MODE="0660", GROUP="input"' \
  | sudo tee /etc/udev/rules.d/99-analogsense.rules

sudo udevadm control --reload-rules && sudo udevadm trigger

Usage

from analogsense import AnalogSense

as_ = AnalogSense()
devices = as_.get_devices()

if not devices:
    print("no supported analog keyboards found.")
    exit()

if len(devices) == 1:
    dev = devices[0]
else:
    for i, d in enumerate(devices):
        print(f"  [{i}] {d.product_name}")
    dev = devices[int(input("select device index: "))]

def on_keys(active_keys):
    for k in active_keys:
        # converting the scancode to a nice readable string
        name = as_.scancode_to_string(k["scancode"])
        
        # some providers can return the digital state of the key
        # (what the system perceives the key as pressed or not)
        # other providers that do not support this will return None
        if k["digital"] is not None:
            digital = " [down]" if k["digital"] else " [up]"
        else:
            digital = ""

        print(f"{name:20s} {k['value']:.4f}{digital}")

dev.start_listening(on_keys)
input("press keys... enter to stop.\n")
dev.stop_listening()

The following functions are available on AnalogSense:

  • get_devices() -> list[Device]
  • open_device(vendor_id, product_id) -> Device | None
  • scancode_to_string(scancode: int) -> str

A device instance has the following members:

  • start_listening(handler: Callable[[list[{"scancode": int, "value": float}]], None])
  • stop_listening()
  • product_name: str
  • forget()
  • dev: DeviceHandle

Scancodes

The scancodes provided by this library are primarily HID scancodes; most keys are mapped as seen on usage page 0x07 (A = 0x04, B = 0x05, ...).

Control keys (usage page 0x0C) are mapped in the 0x3__ range, modulo 0x100:

  • 0x3B5 = Next Track
  • 0x3B6 = Previous Track
  • 0x3B7 = Stop Media
  • 0x3CD = Play/Pause
  • 0x394 = Open File Explorer
  • 0x323 = Open Browser Home Page

OEM-specific keys are mapped in the 0x4__ range:

  • 0x401 = Brightness Up
  • 0x402 = Brightness Down
  • 0x403 = Profile 1
  • 0x404 = Profile 2
  • 0x405 = Profile 3
  • 0x408 = Profile Switch
  • 0x409 = Function Key (Fn)

Metadata

Release files for AnalogSensePy 1.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for AnalogSensePy 1.0.7
File Size Uploaded
analogsensepy-1.0.7.tar.gz 12.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for AnalogSensePy 1.0.7
File Interpreter ABI Platform
analogsensepy-1.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 25.9 kB

Release files / analogsensepy-1.0.7.tar.gz

Download URL analogsensepy-1.0.7.tar.gz
Size 12.4 kB
Tags Source
SHA-256 checksum
How to use checksums
7939778f1516bff028f29c5f597f64ec09e0d528067b313b76cd15ef4f252488
BLAKE2b-256 checksum
How to use checksums
a0f6e02b2fdc3cee6a58d9e279a07081fe6a3c63383b471fb3f81414c4691443
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 6, 2026.

Transparency log

Release files / analogsensepy-1.0.7-py3-none-any.whl

Download URL analogsensepy-1.0.7-py3-none-any.whl
Size 13.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e33d489602a255b1bc4e6d0b12e4e967849b8d1a3ee037862333fb017d7d8ceb
BLAKE2b-256 checksum
How to use checksums
92c53af4cdee8e968c5b373e15fc9b28754b1ec10c668aeb8455feb2d4e12c7e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.7 This release

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page