PsychoPy is a library now, not the application people still expect
For running psychology and neuroscience experiments
At a glance
- What is it?
- The psychopy repository ships the Python library for behavioural experiments while both graphical interfaces live in separate projects, so anyone expecting the Builder interface from a single install is looking at the wrong repository.
- Who is it for?
- PsychoPy fits a lab that wants reproducible, timing-sensitive stimuli from Python alone and has no interest in a graphical front end. It does not fit a course that needs Builder from one checkout, and the version floor blocks any plan to move a lab interpreter to 3.13.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The repository holds the library, not the interfaces
PsychoPy is an open-source package for creating experiments in behavioural science, aimed at researchers who need a stimulus presented at a controlled moment in a script and the timing of that presentation logged next to the response. Its stated goals are precision enough for psychophysics, easy enough for teaching, and the ability to run an experiment in a local Python script or online in JavaScript. What changed is where the code lives. This repository now contains only the PsychoPy library, with the application user interface split into psychopy-studio for the modern web-based GUI and psychopy-app for the legacy wxPython GUI. Application and library are both written in Python and the package is platform independent, so what remains here is a library other front ends call rather than a program you launch. The default branch is dev, which means a fresh clone hands you the development line rather than a packaged build. The declared metadata is short:
[project]
name = "psychopy"
dynamic = ["version"]
requires-python = ">=3.10, <3.13"Because the version itself is dynamic, the number a resolver sees comes from packaging at build time, not from a line you can read in this file.
The dependency list is a map of the runtime
Reading pyproject.toml tells you what the library actually touches while an experiment is running. Stimulus drawing leans on numpy, scipy and matplotlib, and two windowing stacks sit side by side, pyglet for one backend and glfw for the other. A comment in the same file warns that pyGLFW is published as glfw while the pyglfw package is a different project, a naming collision worth knowing before you spend an afternoon on a failing import. That comment also records that glfw 2.5.7 added PYGLFW_LIBRARY_VARIANT, which psychopy/__init__.py reads to pick the X11 build on Linux. Audio runs through soundfile, sounddevice and psychtoolbox, imageio and imageio-ffmpeg handle media, and a data stack of pandas, openpyxl and xmlschema sits beside questplus for instrument control.
dependencies = [
"numpy",
"scipy", # NB scipy 1.16 requires py311; 1.14 requires py310
"pyglet >= 2, < 3",
"glfw>=2.5.7",
"soundfile",
"sounddevice",
"psychtoolbox",Qt arrives through pyqt6, a compiled GUI stack inside a library that otherwise treats the interface as somebody else's problem.
A 3.9 classifier sits under a 3.10 floor
The metadata contradicts itself about Python versions, and the contradiction sits in the file a resolver reads. requires-python is set to >=3.10, <3.13, so an install on 3.9 is refused outright and so is one on 3.13 or anything newer. The classifier list in the same file still advertises Programming Language :: Python :: 3.9 next to 3.10 and 3.11.
classifiers = [
"Development Status :: 4 - Beta",
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3.9",A classifier is text for a listing page rather than a constraint, so the floor in requires-python is what a package manager enforces and the 3.9 line is stale advertising left in the file. The ceiling matters just as much, because on a 3.13 interpreter this package will not resolve and no fallback is offered anywhere in the metadata. Anyone budgeting a Python upgrade for a shared lab machine needs to see that before planning the move.
A second version signal sits in the comment attached to the scipy dependency, which notes that scipy 1.16 requires py311 while 1.14 requires py310. The usable scipy floor therefore moves with your interpreter, which is why the file records it as a comment instead of a hard specifier.
Binary backends decide where an install actually works
Psychophysics runs on frame timing and a sound trigger, so the backends here are not interchangeable conveniences. glfw 2.5.7 is required because the X11 build selection on Linux hangs off the PYGLFW_LIBRARY_VARIANT variable that version introduced, and an older glfw leaves that selection unavailable to psychopy/__init__.py. Apple Silicon gets its own marker, with psychtoolbox held at 3.0.22.2 or newer on Darwin arm64 because earlier wheels build from source on that platform and cannot find the PortAudio and libusb libraries they need. On an Intel Mac the marker does not apply at all. A pinned pyglet below 3 closes the same kind of gap.
What is missing from the visible text matters too. The dependency list is cut off mid-entry at pywinhook, which belongs to the iohub input path, so the Windows-specific half of event capture is only partly readable from what a reader can see here. Expect to confirm the rest against your own platform before assuming the input stack behaves the same everywhere.
Two CI workflows run against both branch lines
The top level of the repository is a working project rather than a bare package directory. building/ and conda/ hold packaging work, docs/ holds the documentation sources, and uv.lock sits next to pyproject.toml, which is how the dependency set gets pinned for repeatable environments. pytest.ini and codecov.yml configure the test run and its coverage reporting, while two workflows named pytests.yaml and CodeQL.yaml each carry badges for the dev branch and for the stable branch, so tests and static analysis run against both lines.
The cadence is visible in the versions themselves: 2026.2.2 on 2026-08-19, 2026.2.3 on 2026-08-27 and 2026.2.4 on 2026-09-14, three builds inside a month. A change in the leading series number marks a development cycle rather than a patch, so a lab pinned to one series should expect real movement when the number advances. The classification the project gives itself, Development Status :: 4 - Beta, is the honest summary of that cadence.
Where the graphical Builder went, and what it costs
The Builder interface that most people name when they say PsychoPy is not in this repository. It lives in psychopy-studio as a web-based GUI and in psychopy-app as the legacy wxPython GUI, so anyone following an older tutorial that opens Builder from a Python package finds a code path that no longer exists here. That split is the real upgrade cost for an established lab: the library moves on its own schedule, the interface moves on another, and a workflow bound to the legacy front end is bound to a different project entirely.
The terms are worth reading before any of that. The project is distributed under GPL-3.0, which means a distributed script that imports psychopy carries copyleft terms onto the combined work. Analysis that never leaves your own machines is a different situation from shipping a modified library or a bundled application to collaborators at another institution, and the latter belongs to whoever owns your institution's policy rather than to this project.
Where PsychoPy is the wrong tool
Three situations rule it out. If your stimuli need frame-accurate rendering on a display you control directly, per-platform backend pins will cost debugging hours that a tight timing budget cannot absorb. If your institution has standardised on a different scripting ecosystem for experiments, the GPL-3.0 terms apply to code you ship across institutional lines, which can stall a collaboration before any data is collected. And if you are teaching a first Python course, a floor at 3.10 plus a pyqt6 dependency means students install a compiled GUI stack to draw a rectangle on screen, which is a lot of machinery for one lesson.
The narrower fit is a working lab with its own environment, stimuli that need repeatable timing, and no interest in a graphical front end at all. For that group the library plus its pinned backends is the whole value, and the two separate interface repositories cost nothing.
Editorial conclusion
PsychoPy fits a lab that wants reproducible, timing-sensitive stimuli from Python alone and has no interest in a graphical front end. It does not fit a course that needs Builder from one checkout, and the version floor blocks any plan to move a lab interpreter to 3.13. Before installing, put the requires-python range next to the Python already running on your own machines, then read the classifiers, which still advertise Python 3.9 while the metadata refuses it, and start from the 2026.2.4 line rather than the default dev branch.
Frequently asked questions
What Python versions does the current PsychoPy support?
The project metadata sets requires-python to >=3.10, <3.13, so interpreters older than 3.10 and anything at or above 3.13 are both refused by a resolver.
Does this repository contain the PsychoPy Builder interface?
No. The repository holds the library only, with the graphical interfaces split into psychopy-studio for the modern web-based GUI and psychopy-app for the legacy wxPython GUI.
Why is psychtoolbox required at a specific version on Apple Silicon?
On Darwin arm64 the dependency is marked as psychtoolbox>=3.0.22.2 because earlier wheels build from source on that platform and cannot find the PortAudio and libusb libraries they need.
What is PYGLFW_LIBRARY_VARIANT used for?
It was added in glfw 2.5.7 and is read by psychopy/__init__.py to select the X11 build of the GLFW backend on Linux.
How quickly does PsychoPy ship new versions?
Three versions landed inside a month: 2026.2.2 on 2026-08-19, 2026.2.3 on 2026-08-27 and 2026.2.4 on 2026-09-14.
Do I need the compiled PyQt6 stack to run PsychoPy experiment scripts?
The library lists pyqt6 among its required dependencies, so a standard install pulls in that stack rather than treating it as an optional extra.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/psychopy-psychopy)Was this useful?