Short answer: curl: command not found almost always means curl is not installed. Minimal Linux images leave it out, and the Debian installer does not add it either (it installs wget instead), so the fix is one package: on Debian and Ubuntu run the two lines below, on Alpine apk add curl, on Rocky, AlmaLinux and Fedora sudo dnf install -y curl. Only when curl is installed and the shell still cannot find it do you have a PATH problem.
sudo apt update
sudo apt install -y curlThe exact wording of the error tells you which shell printed it, and that usually tells you the cause. Find your message in the table and jump to its section.
Which error do you see?
| Message | Printed by | Cause and fix |
|---|---|---|
bash: curl: command not found | bash in a terminal window; with a leading -bash: in an SSH session (a login shell) | Not installed. Install curl |
zsh: command not found: curl | zsh, the default shell on macOS | On macOS, which ships curl, a broken PATH: repair PATH. On Linux, not installed: install curl |
/bin/sh: 1: curl: not found | dash (Debian, Ubuntu) in a Dockerfile RUN line or a cron job; a #!/bin/sh script prints its own name and line instead, as in ./install.sh: 3: curl: not found | Not installed; in a Dockerfile, the image has no curl. Docker |
-sh: curl: not found | BusyBox ash on Alpine, logged in over SSH; sh: in a container shell, /bin/sh: in a Dockerfile RUN line, -ash: on OpenWrt | Not installed. Alpine and OpenWrt |
sudo: 'curl': command not found | sudo-rs, the default sudo on Ubuntu 25.10 and 26.04; classic sudo prints sudo: curl: command not found | Not installed, or only on your own PATH. sudo |
Command 'curl' not found, but can be installed with: | Ubuntu's command-not-found helper | Not installed. Take the apt line. Ubuntu |
exec: "curl": executable file not found in $PATH | docker exec, kubectl exec, a container health check | The image has no curl. Docker |
bash: /snap/bin/curl: No such file or directory | bash, after curl moved or was removed | The shell remembers the old path. hash -r |
'curl' is not recognized as an internal or external command, | Windows cmd | Old Windows or a broken PATH. Windows |
The shell messages were reproduced with bash 5.2, dash 0.5.12, zsh 5.9 and BusyBox 1.35, and all of them end the command with exit status 127 (sudo exits with 1). The sudo-rs and Ubuntu helper wording comes from their source code.
First: which system are you on?
If you are not sure what you are logged into, ask the system rather than guessing. The package manager is what matters, not the marketing name.
grep -E '^(ID|VERSION_ID)=' /etc/os-releaseVERSION_ID="12"
ID=debianThe ID line tells you the family: debian and ubuntu use apt, alpine uses apk, rocky, almalinux, rhel and fedora use dnf.
Installing curl
Debian and Ubuntu
Update the package index first. On a fresh image it is empty, and apt then answers E: Unable to locate package curl (on Debian 13 and Ubuntu 26.04, apt starts the line with Error:), the most common follow-up problem.
sudo apt update
sudo apt install -y curlWhy Debian has no curl: the installer’s “standard system utilities” task installs every package of priority standard. wget has that priority, curl is optional, in Debian 12 and 13 alike. So a Debian server set up from the installer has wget but not curl, and Debian container images have neither. Debian’s official cloud images do add curl, so on a VPS it depends on the template. Docker’s ubuntu images lack curl as well.
On Ubuntu an interactive shell often answers with the command-not-found helper instead of the plain error. With snapd installed it offers a snap first:
Command 'curl' not found, but can be installed with:
sudo snap install curl # version SNAP_VERSION, or
sudo apt install curl # version DEB_VERSION
See 'snap info curl' for additional versions.Take the apt line. The curl snap runs under strict confinement and cannot write everywhere a normal curl can; the rustup installer, for one, failed with curl: (23) Failure writing output to destination because of it. If you already installed the snap, swap it:
sudo snap remove curl
sudo apt install -y curl
hash -rIf apt update itself fails with Temporary failure resolving, the server cannot reach DNS, which no package fixes. Temporary failure in name resolution has the checks for that. If Unable to locate package stays after an update, see E: Unable to locate package.
Alpine Linux: apk add curl
Alpine is what most slim Docker images are built on. Its base image has a BusyBox wget but no curl. As root:
apk add curlIn a Dockerfile, use --no-cache, which fetches a fresh package index and leaves nothing behind in the image layer:
RUN apk add --no-cache curlAlpine’s shell is BusyBox ash, which is why the message reads sh: curl: not found, -sh: curl: not found in a login shell over SSH, and /bin/sh: curl: not found in a Dockerfile RUN line. If the container runs as an unprivileged user, apk refuses to write its database; open a root shell in it instead (docker exec -u 0 -it CONTAINER sh), and put the permanent fix in the Dockerfile.
OpenWrt uses BusyBox too, but its root shell is called ash, so a router prints -ash: curl: not found. OpenWrt 25.12 and later use apk (apk update && apk add curl); 24.10 and older use opkg (opkg update && opkg install curl).
Rocky, AlmaLinux, RHEL and Fedora
sudo dnf install -y curlReleases from before dnf, such as CentOS 7 and RHEL 7, use yum:
sudo yum install -y curlArch and openSUSE
sudo pacman -S --noconfirm curlsudo zypper install -y curlInside a Docker container
Two things differ in a container: you are usually already root, so sudo does not exist, and the package index is empty because the image was built without it. When you call curl from outside, through docker exec, kubectl exec or a HEALTHCHECK, the runtime reports the missing binary in its own words:
OCI runtime exec failed: exec failed: unable to start container process: exec: "curl": executable file not found in $PATH: unknownFor a one-off test, install it in the running container:
apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*Then do it properly in the Dockerfile. Anything installed by hand is gone the moment the container is recreated, and a health check that calls curl fails on every fresh container until the image carries it.
FROM debian:13-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*Images built FROM scratch and distroless images have no package manager and often no shell. There the only fix is a different base image, or a health check written in the application’s own language.
“sudo: curl: command not found”
Classic sudo (Debian, RHEL, Ubuntu 24.04 and older) prints sudo: curl: command not found. sudo-rs, the default sudo since Ubuntu 25.10, quotes the name: sudo: 'curl': command not found. Both mean the same, and there are two causes:
- curl is not installed at all. Plain
curlfails too. Install it as shown above. - curl works without sudo but not with it. sudo does not use your PATH. It replaces it with
secure_pathfrom/etc/sudoers: on Debian and Ubuntu/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin(Ubuntu adds/snap/bin), on RHEL, Rocky and Alma 9 and 10 only/sbin:/bin:/usr/sbin:/usr/bin. A curl from a conda environment, Homebrew on Linux,~/.local/binor, on RHEL,/usr/local/binis invisible to sudo.
command -v curl # where your shell finds curl
sudo sh -c 'command -v curl' # where sudo finds it; empty means nowhereThe clean fix is the distribution package, which lands in /usr/bin where every PATH looks. For a one-off, pass the full path: sudo "$(command -v curl)" -fsSLO URL.
One trap: in curl -fsSL URL | sudo bash, sudo only applies to bash. curl runs as you, so a missing curl shows up as bash: curl: command not found, not as a sudo error. For sudo itself missing, see sudo: command not found.
When curl is installed but still “not found”
Check that the file exists first: ls -l /usr/bin/curl. If it is there and the shell still refuses, there are four realistic causes.
- The shell remembers an old location. bash and zsh cache where they found a command. If curl moved, for example from
/snap/binto/usr/bin, bash keeps trying the old path and printsbash: /snap/bin/curl: No such file or directory. Runhash -rin bash orrehashin zsh, or open a new shell. - A startup file overwrote PATH. If
lsorgrepare “not found” as well, a line such asexport PATH=/opt/tool/binwithout:$PATHreplaced the whole search list. That is also the only way to getzsh: command not found: curlon a Mac, where curl is part of the system in/usr/bin. Restore a working PATH for this session, then fix the line in~/.bashrc,~/.profile,~/.zshrcor~/.zprofile. - PATH lists the file instead of its directory. Advice like
export PATH=$PATH:/usr/bin/curldoes nothing: PATH entries are directories, and the shell looks for/usr/bin/curl/curl. Add the directory that contains the binary. - You are in a restricted environment. Some managed shells and minimal containers have no package manager at all. There the answer is an image or a host with curl baked in.
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binexport PATH=/usr/bin:/bin:/usr/sbin:/sbincurl on Windows
Windows 10 version 1803 and later, Windows 11 and Windows Server 2019 and later ship curl.exe in C:\Windows\System32. In cmd, a missing curl reads:
'curl' is not recognized as an internal or external command,
operable program or batch file.That means an older Windows or a PATH that lost System32. Install curl with winget install cURL.cURL, or use PowerShell’s Invoke-WebRequest. The more common Windows problem is the opposite: in Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest, so curl options fail with A parameter cannot be found that matches parameter name. Type curl.exe to get the real program; PowerShell 7 dropped the alias. Inside WSL you are on Linux, so the Ubuntu command above applies.
Verify that it worked
command -v curl
curl --version | head -1
curl -sSI https://example.com | head -1/usr/bin/curl
curl 7.88.1 (x86_64-pc-linux-gnu) libcurl/7.88.1 OpenSSL/3.0.22 zlib/1.2.13 brotli/1.0.9 zstd/1.5.4 libidn2/2.3.3 libpsl/0.21.2 (+libidn2/2.3.3) libssh2/1.10.0 nghttp2/1.52.0 librtmp/2.3 OpenLDAP/2.5.13
HTTP/2 200The first line is the path the shell will run, the second the version, the third a real HTTPS request. A curl: (77) error on the third line means ca-certificates is missing; curl: (6) Could not resolve host means DNS, not curl.
If you cannot install anything
On a locked-down box you may not be allowed to add packages. Two substitutes cover most one-off downloads:
wget is often there when curl is not: a Debian system set up with the installer has it, and so does Alpine’s BusyBox.
wget -qO- https://example.comFailing that, bash can open a TCP socket on its own, for plain HTTP only, no TLS:
exec 3<>/dev/tcp/example.com/80
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' >&3
cat <&3If wget is missing as well, wget: command not found covers it the same way.
A note on fresh servers
If you meet this error on a brand-new VPS, it is worth spending the same five minutes on the rest of the base setup: a non-root user, key-only SSH and automatic security updates, all in the initial server setup checklist. Need a box to try this on? An Ubuntu VPS or a Debian VPS on the Standard KVM line comes from a template: Debian 13, 12 or 11, Ubuntu 24.04, 22.04 or 20.04, and CentOS Stream or Rocky Linux 9 as well.
Another tool missing, or a directory to add to PATH for good in bash, zsh and fish? See command not found: the three causes and the fix for every tool.
Frequently asked
Why does Debian say curl: command not found on a fresh install?
Debian rates curl an optional package, so the installer's standard system utilities bring in wget but not curl, in Debian 12 and 13 alike. Run 'sudo apt update && sudo apt install -y curl'. In a Debian container, drop sudo and install ca-certificates with it.
Ubuntu offers 'sudo snap install curl' and 'sudo apt install curl': which one?
Take apt. The command-not-found helper lists the snap first, but the curl snap is strictly confined and can fail to write files, for example with 'curl: (23) Failure writing output to destination'. If you installed the snap, run 'sudo snap remove curl', install the apt package and run 'hash -r'.
What does sudo: 'curl': command not found mean?
It is how sudo-rs, the default sudo on Ubuntu 25.10 and 26.04, words it; classic sudo prints sudo: curl: command not found. Either curl is not installed, or it sits in a directory outside sudo's secure_path, such as ~/.local/bin or a conda environment. Install the distribution package or give sudo the full path.