Introducing PsychoPy Studio

PsychoPy Studio is a full rebuild of the PsychoPy desktop app using web-based libraries (Svelte and Electron). You can download PsychoPy Studio from psychopy.org or from the PsychoPy repo on GitHub.

The underlying experiment engine (the PsychoPy library) is still Python, but Studio gives a new front-end application for creating, editing and running experiments, with some major advantages over the existing Python-based standalone app:

Modern interface

A lot of software engineers in the world of user-interface development, in recent years, have been focussed on building web applications. This means that JavaScript is where the most modern user interfaces are being written, so by moving to web-based libraries for Studio we’re able to create a much more polished, modern-feeling app. It doesn’t look vastly different, because we think there were a lot of good things about the existing interface that we wanted to keep, but we’re hoping you’ll notice a lot of small improvements to the usability and overall feel of the app.

For example: Components and Routines in Studio can be rearranged by drag n’ drop (see below…).

Faster load times

We all know that the PsychoPy application has always taken a very long time to launch. You don’t want to shut it down for fear of having to watch another iteration of that splash screen!

PsychoPy Studio is much faster to load as we don’t have to start Python for the app itself to appear; all that can happen in the background once the app is open, meaning you can get to editing your experiment quicker.

Easier installations

PsychoPy Studio doesn’t come with Python baked in; when you first open the app, it uses a package manager called uv to set up its own environment and install just the PsychoPy library, without any of the app-specific dependencies like wxPython (which is pretty large and tricky to compile). This makes the installation process much quicker and easier.

In particular, installing on Linux is much easier, as we’re now able to offer a standalone (.AppImage) Linux installer.

Better version independence

PsychoPy has, for many years, supported the rare (possibly unique?) ability to switch itself to an older state so that you could install a newer version of the app but run your study in the version of the library you created it in. We think that’s a very important feature of the software for the sake of reproducibility.

However, we’ve always been limited by the Python version and dependencies of the app. If you installed a version of PsychoPy that shipped with Python 3.10, then you could only use version of the library which supported Python 3.10 (which means at least PsychoPy 2023.2.x).

As PsychoPy Studio doesn’t have Python baked in, it can setup a whole environment on the fly, meeting the needs of a given legacy version. Each environment can even have its own plugins installed, independent of one another. And you can have as many environments as you like, for as many versions as you need to support in your lab!

The future: Creating studies in Pavlovia and on tablets

When we say PsychoPy Studio is made using web-based technology, what we mean is that the interface of the app is a webpage which we package inside of a desktop app. With a bit of work, this same webpage could be hosted online and accessed by your web browser, meaning editing experiments on a tablet, a Chromebook, etc. would be possible with no installation required! We’re hoping to take Studio in this direction in the near future, so watch this space.

Very excited to play with Studio!

I am, however, having an issue with linking to a Pavlovia project in Studio. I can log in to Pavlovia in the app from the No User dropdown in the menu bar, but when I do No Project > New Project, or if I do No Project > Search Projects, nothing happens.

(With developer tools enabled, nothing appears in the console while doing these)

Similarly, if I open an existing experiment that is already linked to a Pavlovia project (i.e., there is a .git folder in the project directory), Studio doesn’t seem to know that it’s got a Pavlovia project.

Is this currently expected behavior, with Pavlovia support still to come; or am I doing something wrong/is this a bug?

That does sound like a bug, I think it’s best to create a new thread for it here and/or report it on the github issues for psychopy-studio .

Thanks— I’ll go post a github issue.

I can confirm that the latest release (2026.1.1) seems to resolve this issue.

What is the expected behavior for Manage Local Projects > Import projects? I had assumed that pointing to a folder with a .psyexp file and/or a .git folder would work, but neither of these can be selected.

Absolutely excited for Studio! Playing around with the beta now and particularly loving how lightweight it is.

That said, I’ve noticed that the coder view sometimes fails to save script changes, despite the IDE showing visual feedback that the script has been saved. If I then run the script, it will run an older version (i.e., the last version that was successfully saved), suggesting that the IDE somehow loses its ability to save script changes over time. Reopening the script fixes this issue, but I lose all unsaved progress.

The relevant file is the projects.json file in the pavlovia folder in the PsychoPy user folder; the idea was to support running in browser by letting you upload the file which the installed app uses, but maybe that option adds more confusion than it’s worth.

That does sound like something’s gone wrong while saving the file; same as with @abraver’s bug, either create a new thread here or open an issue on the psychopy-studio repo and we’ll try to figure it out :slight_smile: If you can attach the last-app-load.log file from your PsychoPy user folder (Tools → Open PsychoPy User Folder to access it) that would be helpful, I suspect there’ll be an error in there which didn’t make it to the Runner’s stdout panel.

on 2026.2.3 I am having some issues with version control. I saved a .psyexp as 2025.1.1 and tried to start it in Studio and am getting errors for that particular version. It is in the menu of available versions.

unning C:/Users/HN_Lab_405/Desktop/Experiments/Mem_Context/DS_Mem_Context_Emo_Encoding/mem_context_emo_ET_DS123.py...
Traceback (most recent call last):
  File "C:\Users\HN_Lab_405\Desktop\Experiments\Mem_Context\DS_Mem_Context_Emo_Encoding\mem_context_emo_ET_DS123.py", line 15, in <module>

    psychopy.useVersion('2025.1.1')
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\psychopy\tools\versionchooser.py", line 256, in useVersion

    reqdMajorMinorPatch = fullVersion(requestedVersion)
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\psychopy\tools\versionchooser.py", line 494, in fullVersion

    for tag in availableVersions(local=False):
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\psychopy\tools\versionchooser.py", line 477, in availableVersions

    list(set([psychopy.__version__] + _localVersions(forceCheck) + _remoteVersions(
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\psychopy\tools\versionchooser.py", line 404, in _localVersions

    tagInfo = subprocess.check_output(cmd.split(), cwd=VERSIONSDIR,
  File "C:\Users\HN_Lab_405\AppData\Roaming\uv\python\cpython-3.10.18-windows-x86_64-none\lib\subprocess.py", line 421, in check_output

    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "C:\Users\HN_Lab_405\AppData\Roaming\uv\python\cpython-3.10.18-windows-x86_64-none\lib\subprocess.py", line 503, in run

    with Popen(*popenargs, **kwargs) as process:
  File "C:\Users\HN_Lab_405\AppData\Roaming\uv\python\cpython-3.10.18-windows-x86_64-none\lib\subprocess.py", line 971, in __init__

    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\HN_Lab_405\AppData\Roaming\uv\python\cpython-3.10.18-windows-x86_64-none\lib\subprocess.py", line 1456, in _execute_child

    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] The system cannot find the file specified

Finished running C:/Users/HN_Lab_405/Desktop/Experiments/Mem_Context/DS_Mem_Context_Emo_Encoding/mem_context_emo_ET_DS123.py

2026.2.0 Does not seem to have this behavior… It will produce some warnings but I can run the older experiment

>> "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1\Scripts\python.exe" -m liaison.constants (timeout = 10000ms)
{"START_MARKER": "LIAISON:CONNECTED", "STOP_MARKER": "LIAISON:DISCONNECTED"}
opening handshake failed
Traceback (most recent call last):
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\websockets\http11.py", line 138, in parse
    request_line = yield from parse_line(read_line)
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\websockets\http11.py", line 309, in parse_line
    line = yield from read_line(MAX_LINE_LENGTH)
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\websockets\streams.py", line 46, in read_line
    raise EOFError(f"stream ends after {p} bytes, before end of line")
EOFError: stream ends after 0 bytes, before end of line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\websockets\server.py", line 545, in parse
    request = yield from Request.parse(
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\websockets\http11.py", line 140, in parse
    raise EOFError("connection closed while reading HTTP request line") from exc
EOFError: connection closed while reading HTTP request line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler
    await connection.handshake(
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1.1\lib\site-packages\websockets\asyncio\server.py", line 207, in handshake
    raise self.protocol.handshake_exc
websockets.exceptions.InvalidMessage: did not receive a valid HTTP request

LIAISON:CONNECTED@localhost:8005
opening handshake failed
Traceback (most recent call last):
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2026.2.0\lib\site-packages\websockets\http11.py", line 138, in parse
    request_line = yield from parse_line(read_line)
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2026.2.0\lib\site-packages\websockets\http11.py", line 320, in parse_line
    line = yield from read_line(MAX_LINE_LENGTH)
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2026.2.0\lib\site-packages\websockets\streams.py", line 46, in read_line
    raise EOFError(f"stream ends after {p} bytes, before end of line")
EOFError: stream ends after 0 bytes, before end of line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2026.2.0\lib\site-packages\websockets\server.py", line 547, in parse
    request = yield from Request.parse(
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2026.2.0\lib\site-packages\websockets\http11.py", line 140, in parse
    raise EOFError("connection closed while reading HTTP request line") from exc
EOFError: connection closed while reading HTTP request line

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2026.2.0\lib\site-packages\websockets\asyncio\server.py", line 356, in conn_handler
    await connection.handshake(
  File "C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2026.2.0\lib\site-packages\websockets\asyncio\server.py", line 207, in handshake
    raise self.protocol.handshake_exc
websockets.exceptions.InvalidMessage: did not receive a valid HTTP request

C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1\lib\site-packages\pyglet\media\codecs\wmf.py:838: UserWarning: [WinError -2147417850] Cannot change thread mode after it is set
  warnings.warn(str(err))

--- Started C:/Users/HN_Lab_405/Desktop/Experiments/Mem_Context/DS_Mem_Context_Emo_Recogniton/mem_context_emo_ET_DS-Recognition070926_legacy_legacy.py ---
C:\Users\HN_Lab_405\AppData\Roaming\psychopy4\.python\2025.1\lib\site-packages\pyglet\media\codecs\wmf.py:838: UserWarning: [WinError -2147417850] Cannot change thread mode after it is set
  warnings.warn(str(err))

Please either create a new thread or raise a GitHub issue for this bug; this thread is just for announcing Studio’s release.

Sorry. I saw other folks had posted issues here.