Description
This article explains how scrcpy works, how to install and update the current release from an official local checkout, and how to connect to an Android device over USB or Wi-Fi. It also covers common operating modes and the failure caused when an older scrcpy binary remains linked to FFmpeg libraries that a Linux upgrade has replaced.
The commands were validated with scrcpy 4.0, a Pixel 7 Pro running Android 16,
and Ubuntu 26.04. Replace release numbers, checksums, device serials, IP
addresses, and ports with the values shown by the current scrcpy release and by
adb on the local system.
How scrcpy Works
Scrcpy is a native host application for Linux, macOS, and Windows. It uses Android Debug Bridge (ADB) over USB or TCP/IP to start a matching scrcpy server on the Android device. The server captures encoded video and audio and sends the streams to the host client, which decodes and displays them. Control messages travel in the other direction.[1][2]
This design has several useful properties:
- The Android device does not need root access.
- No permanent Android app, account, cloud service, or internet connection is required.
- Nothing is left installed on the device after the session ends.
- The client and server must come from the same scrcpy version.
- ADB provides the transport, so every ADB device selector and serial also applies to scrcpy.
Scrcpy does more than screen mirroring. Version 4.0 supports keyboard, mouse, gamepad, and clipboard control; audio forwarding on Android 11 or newer; recording; virtual displays; screen-off operation; Android 12+ camera capture; Linux V4L2 webcam output; and an OTG control-only mode that does not require USB debugging.[1:1]
Choose an Installation Method
Use only the official Genymobile/scrcpy repository and its release assets.
The project explicitly warns against downloads from similarly named third-party
sites.[1:2]
| Method | Best use | Update model | Trade-off |
|---|---|---|---|
| Official Linux release archive | A self-contained, portable copy with the fewest host-library problems | Download and extract each new release | Does not automatically replace a scrcpy command elsewhere on PATH |
Official install_release.sh from a local checkout |
Regular use from Ubuntu while following new upstream releases | git pull --ff-only, then rerun the script |
Rebuild after a major distribution or FFmpeg upgrade |
| Distribution package | Maximum package-manager integration | Updated by the distribution | Debian/Ubuntu packages may substantially lag upstream; scrcpy marks them obsolete |
| Full manual source build | Developing or testing scrcpy itself | Reconfigure and rebuild the selected branch | Requires more build tooling and, when building the Android server, a JDK and Android SDK |
For this host, the local-checkout installation is the best balance. It installs
the command, server, manual page, desktop entries, icons, and shell completions
under /usr/local, while keeping updates explicit and repeatable.[3][2:1]
Prerequisites
Linux host
Install the runtime and client build dependencies documented by scrcpy for Debian and Ubuntu:[3:1]
1 | sudo apt update |
The release installation uses scrcpy’s matching, prebuilt Android server. Java and the Android SDK are therefore unnecessary unless developing the server or building every component from source.
Android device
Normal mirroring requires Android 5.0/API 21 or newer. Audio forwarding requires Android 11 or newer, and camera mirroring requires Android 12 or newer.[1:3]
Enable developer options and USB debugging:[4]
- Open Settings -> About phone.
- Tap Build number seven times.
- Open Settings -> System -> Developer options.
- Enable USB debugging.
- Connect the phone with a data-capable USB cable.
- Unlock the phone and accept the RSA debugging authorization prompt.
Select Always allow from this computer only on a trusted host. Some Android vendors also require a separate USB debugging (Security Settings) option to permit keyboard and mouse input.[1:4]
For Android 11+ wireless pairing, also enable Wireless debugging. The phone and host must be able to reach each other over the local network.[5]
Recommended Installation from the Local Checkout
Clone the official release branch
Scrcpy’s master branch tracks the latest release. The dev branch contains
work intended for the next release.[2:2]
For a new checkout:
1 | mkdir -p "$HOME/Workspace" |
For the existing checkout:
1 | cd "$HOME/Workspace/scrcpy" |
--ff-only prevents an accidental merge commit if local work and upstream have
diverged. Use a separate branch or worktree for scrcpy development rather than
editing the release checkout on master.
Build and install the release
Run the upstream release installer as the normal user:
1 | cd "$HOME/Workspace/scrcpy" |
The script performs these operations:
- Downloads the prebuilt Android server for the release recorded in the checkout.
- Verifies the server’s SHA-256 checksum.
- Recreates
build-autoand builds the native client against the host’s current libraries. - Uses
sudo ninja installto install the resulting files under/usr/local.
Do not run Meson or Ninja themselves as root. Only the final installation step needs elevated privileges.[2:3]
Verify what will run
Shell command lookup is independent of the current directory. Being inside the
scrcpy repository does not make the shell use the local build when the command
scrcpy is entered.
1 | hash -r |
For this installation, command -v should normally print:
1 | /usr/local/bin/scrcpy |
Confirm that its shared libraries all resolve:
1 | ldd "$(command -v scrcpy)" | grep 'not found' || echo 'All libraries resolved' |
Run the build without installing it
The repository launcher takes the build directory as its first argument, then passes all remaining arguments to scrcpy:
1 | cd "$HOME/Workspace/scrcpy" |
This is useful for testing because it explicitly pairs
build-auto/app/scrcpy with build-auto/server/scrcpy-server and ignores an
older command found on PATH.
Update to a new release
When upstream publishes a release:
1 | cd "$HOME/Workspace/scrcpy" |
Review or commit local modifications before pulling. Also rerun the installer after a major Ubuntu or FFmpeg upgrade so the client is linked against the new host library ABI.
Uninstall the source installation
From the same configured build directory:
1 | cd "$HOME/Workspace/scrcpy" |
This is preferable to manually deleting only /usr/local/bin/scrcpy, because
the installation includes the server, manual page, icons, desktop entries, and
shell completions.
Alternative: Official Portable Linux Release
The official x86_64 release archive includes scrcpy, adb, the matching
server, the manual page, and artwork. It avoids the FFmpeg mismatch described
later because the release is packaged as a static Linux build.[3:2]
For the tested 4.0 release:
1 | mkdir -p "$HOME/Applications" |
Before using these commands for another release, copy its filename and checksum from the official release page. Do not reuse the 4.0 checksum for another file.
Connect over USB
Start or refresh ADB and list connected devices:
1 | adb kill-server |
A healthy authorized connection resembles:
1 | List of devices attached |
The state must be device:
unauthorizedmeans the phone must be unlocked and the RSA prompt accepted.offlineusually requires reconnecting the phone or restarting ADB.- An empty list means ADB cannot communicate with it. Try another data cable, a direct host port, and an ADB restart.
If only one device is connected, simply run:
1 | scrcpy |
To explicitly select the sole USB device:
1 | scrcpy --select-usb |
When multiple devices exist, use the exact serial from adb devices -l:
1 | scrcpy --serial DEVICE_SERIAL |
Replace scrcpy with ./run build-auto in any example when testing the local
build without installing it.
Connect over Wi-Fi
Scrcpy uses ADB’s network transport. USB and Wi-Fi entries for the same phone count as separate ADB devices and have different serials.[6]
Method 1: Switch an authorized USB device to TCP/IP
With the device connected and authorized over USB, scrcpy can discover its IP, enable ADB TCP/IP mode, connect, and launch in one command:[6:1]
1 | scrcpy --tcpip |
Afterward, disconnect USB and select the network device:
1 | adb devices -l |
The traditional manual equivalent is:
1 | DEVICE_IP=$(adb shell ip route | awk '{print $9; exit}') |
This mode generally remains available only until the device or ADB mode is reset.
Method 2: Pair with Android 11+ Wireless Debugging
This method can establish ADB without a USB cable after the host is paired.[5:1]
- On the phone, open Settings -> System -> Developer options -> Wireless debugging.
- Select Pair device with pairing code.
- Note the pairing IP address, temporary pairing port, and six-digit code.
- On the host, run:
1 | adb pair PHONE_IP:PAIRING_PORT |
Enter the six-digit code. Then return to the main Wireless debugging screen and use its separate IP address & port debugging endpoint:
1 | adb connect PHONE_IP:DEBUG_PORT |
The pairing port and debugging port are different. The debugging port may change when Wi-Fi, wireless debugging, or the phone restarts, so read the current endpoint instead of assuming the previous port remains valid.
Disconnect when finished:
1 | adb disconnect PHONE_IP:DEBUG_PORT |
Disable wireless debugging when it is not needed, especially on an untrusted network.
Useful Operating Modes
These examples cover the main scrcpy capabilities. Run scrcpy --help and use
the linked upstream documentation for all options.
Improve performance on a high-resolution phone
Reducing resolution usually has the largest impact on latency and reliability:
1 | scrcpy --max-size=1920 --max-fps=60 |
Use H.264 if the device does not provide a usable H.265 encoder.
Turn off the physical display while mirroring
1 | scrcpy --turn-screen-off --stay-awake |
Record on the host
1 | scrcpy --record=session.mkv |
Scrcpy records the encoded streams directly rather than screen-capturing its window, so transport jitter does not contaminate the recording timestamps.[7]
Use read-only or control-only mode
1 | scrcpy --no-control |
Use better keyboard and mouse emulation
1 | scrcpy --keyboard=uhid --mouse=uhid |
UHID makes Android treat the host devices more like physical peripherals and also works over Wi-Fi. Standard SDK input is still the default.
Capture the Android camera
On Android 12 or newer:
1 | scrcpy --list-cameras |
On Linux, camera or display video can also be sent to a configured V4L2 loopback device for OBS or video-conferencing software:[8]
1 | scrcpy --video-source=camera --camera-facing=front \ |
Start an app in a temporary virtual display
1 | scrcpy --new-display=1920x1080 --start-app=org.videolan.vlc |
The virtual display is destroyed when scrcpy exits unless other options change that behavior.[9]
Control over USB without ADB
OTG mode emulates physical input devices through Android Open Accessory. It requires USB but not USB debugging. It intentionally provides no video or audio:[10]
1 | scrcpy --otg |
Clipboard and file transfer
Clipboard synchronization is enabled by default. Avoid pasting sensitive
content because it becomes available to Android applications through the
Android clipboard. Drag an APK onto the scrcpy window to install it, or drag a
different file to push it to /sdcard/Download/.[11]
Troubleshooting
error while loading shared libraries: libavformat.so.61
This exact error occurred after the host upgraded to Ubuntu 26.04:
1 | scrcpy: error while loading shared libraries: libavformat.so.61: |
The /usr/local/bin/scrcpy executable was an older unmanaged build linked to
FFmpeg 7 libraries such as libavformat.so.61. Ubuntu now supplied FFmpeg 8
libraries such as libavformat.so.62. The local scrcpy 4.0 build was already
correctly linked and ran normally.
Diagnose this class of failure with:
1 | type -a scrcpy |
First confirm that the local build works:
1 | cd "$HOME/Workspace/scrcpy" |
Then rebuild and replace the stale installation:
1 | git switch master |
If build-auto was just built from the current checkout and already works, the
existing build can be installed directly:
1 | sudo ninja -C build-auto install |
Never create a compatibility symlink such as libavformat.so.61 -> libavformat.so.62. Different SONAME major versions indicate incompatible ABIs;
making the loader accept the wrong library can cause crashes or data corruption.
Common connection and runtime failures
| Symptom | Likely cause | Corrective action |
|---|---|---|
adb devices -l is empty |
USB transport did not enumerate or ADB retained stale state | Unlock and reconnect the phone, try another data cable or direct USB port, then restart ADB. |
Device is unauthorized |
Host key has not been approved | Accept the RSA prompt. Revoke USB debugging authorizations and reconnect if the prompt never appears. |
Device is offline |
Stale or interrupted ADB transport | Reconnect the device and run adb kill-server && adb start-server. |
adb push reports failed to read copy response and the device disappears |
USB reset during server upload | Change the cable or port, avoid an unstable hub, and use wireless debugging if resets continue. |
| scrcpy reports more than one device | USB and TCP/IP transports are both active | Use --select-usb, --select-tcpip, or --serial SERIAL. |
| Server version does not match client | The local client and Android server came from different releases | Rerun install_release.sh, or rebuild with the exact server for the checked-out tag. |
| Meson reports incompatible build data | Meson changed after the build directory was configured | Let install_release.sh recreate build-auto, or use a new build directory for manual development. |
adb connect cannot reach the phone |
Wrong endpoint, different LAN, client isolation, firewall, or VPN route | Re-read the current endpoint, verify LAN reachability, and check firewall/VPN policy. |
| Audio is unavailable | Android is too old or the app/device blocks capture | Audio requires Android 11+. Unlock Android 11 before startup; use --no-audio when it is not required. |
| Wayland cannot set the window icon | Compositor lacks an optional icon protocol | Ignore the warning if the video window otherwise works. |
To determine whether Linux still sees a USB phone that ADB does not list:
1 | lsusb | grep -Ei 'Google|Pixel|18d1' |
If lsusb sees the device but ADB does not, restart ADB after reconnecting it.
Repeated kernel disconnect and re-enumeration events point toward the cable,
port, hub, or USB controller rather than scrcpy.
Repeat-Use Checklist
Update or repair the installed release:
1 | cd "$HOME/Workspace/scrcpy" |
Start a USB session:
1 | adb devices -l |
Start an already paired wireless session:
1 | adb connect PHONE_IP:DEBUG_PORT |
Test the repository build without changing the installed command:
1 | cd "$HOME/Workspace/scrcpy" |
Sources
Title: scrcpy README and prerequisites
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎Title: Build scrcpy
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎ ↩︎ ↩︎ ↩︎Title: Install scrcpy on Linux
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎ ↩︎ ↩︎Title: Configure on-device developer options
Publication: Android Developers ↩︎Title: Android Debug Bridge: Connect to a device over Wi-Fi
Publication: Android Developers ↩︎ ↩︎Title: scrcpy connection documentation
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎ ↩︎Title: scrcpy recording documentation
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎Title: scrcpy Video4Linux documentation
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎Title: scrcpy virtual display documentation
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎Title: scrcpy OTG documentation
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎Title: scrcpy control, clipboard, and file-drop documentation
Publication: Genymobile/scrcpy
Version: 4.0 ↩︎