These are typical situations where GURL is useful:
- I need to download one file but
curlis not installed. - I need HTTPS but OpenSSL is unavailable.
- I need a standalone HTTP client with no external runtime dependencies.
- I need an HTTP client for an old or unusual operating system.
- I need the same command-line utility on Linux, BSD, macOS, and Windows.
- I need a curl-like utility compiled with TLS support already included.
That's what GURL is for.
One binary.
No external libraries.
HTTP and HTTPS.
Runs on a lot of platforms.
GURL is a small, standalone command-line HTTP/HTTPS client written in Go.
It is designed for situations where you just need to download a new software on an old system, call an HTTPS endpoint, send POST data, or make a simple request — without installing curl, OpenSSL, or a collection of shared libraries.
TLS support is built into the binary through Go's standard library. GURL also embeds the Mozilla CA bundle published by curl, so certificate verification does not depend on an old or missing CA store on the host operating system.
This makes GURL especially useful for:
- installing new software on old operating systems
- servers where
curlor OpenSSL is unavailable or outdated
Just download one executable and run it.
gurl https://example.comIf no protocol is specified, GURL uses http://:
gurl example.com
Universal installer / Универсальная установка
auto-detect OS/ARCH · root → /bin · user → ~/.local/bin
For Unix-like systems you can use one bootstrap installer.
It detects the operating system and CPU architecture, downloads the correct GURL binary using an available native downloader, and selects the installation path automatically:
- if the installer runs as root →
/bin/gurl - if it runs as a normal user →
~/.local/bin/gurl
After installation it immediately prints ready-to-copy examples showing how to run GURL.
Normal user:
sh install-gurl.shSystem-wide:
sudo sh install-gurl.sh#!/bin/sh
set -u
BASE_URL="${GURL_BASE_URL:-http://files.zabiyaka.net/gurl/latest}"
have() {
command -v "$1" >/dev/null 2>&1
}
die() {
echo "gurl-install: $*" >&2
exit 1
}
say() {
echo "gurl-install: $*"
}
# Detect OS
UNAME_S="$(uname -s 2>/dev/null || echo unknown)"
case "$UNAME_S" in
Linux)
if [ -n "${ANDROID_ROOT:-}" ] ||
[ -n "${ANDROID_DATA:-}" ] ||
[ -n "${TERMUX_VERSION:-}" ]; then
OS="android"
else
OS="linux"
fi
;;
Darwin) OS="mac" ;;
FreeBSD) OS="freebsd" ;;
OpenBSD) OS="openbsd" ;;
NetBSD) OS="netbsd" ;;
DragonFly) OS="dragonfly" ;;
SunOS)
SUN_VERSION="$(uname -v 2>/dev/null || true)"
if echo "$SUN_VERSION" | grep -i illumos >/dev/null 2>&1; then
OS="illumos"
elif [ -r /etc/release ] &&
grep -Ei 'illumos|OpenIndiana|OmniOS|SmartOS' /etc/release >/dev/null 2>&1; then
OS="illumos"
else
OS="solaris"
fi
;;
AIX) OS="aix" ;;
*) die "unsupported operating system: $UNAME_S" ;;
esac
# Detect architecture
if [ "$OS" = "aix" ]; then
ARCH="ppc64"
else
UNAME_M="$(uname -m 2>/dev/null || echo unknown)"
case "$UNAME_M" in
x86_64|amd64) ARCH="amd64" ;;
i386|i486|i586|i686|x86) ARCH="386" ;;
aarch64|arm64) ARCH="arm64" ;;
armv4*|armv5*|armv6*|armv7*|armv8l|arm) ARCH="arm" ;;
loongarch64|loong64) ARCH="loong64" ;;
mips64el|mips64le) ARCH="mips64le" ;;
mips64) ARCH="mips64" ;;
mipsel|mipsle) ARCH="mipsle" ;;
mips) ARCH="mips" ;;
ppc64le|powerpc64le) ARCH="ppc64le" ;;
ppc64|powerpc64) ARCH="ppc64" ;;
riscv64) ARCH="riscv64" ;;
s390x) ARCH="s390x" ;;
*) die "unsupported CPU architecture: $UNAME_M" ;;
esac
fi
# Verify that this build exists
case "$OS/$ARCH" in
linux/amd64|linux/arm64|linux/386|linux/arm|linux/loong64|\
linux/mips|linux/mipsle|linux/mips64|linux/mips64le|\
linux/ppc64|linux/ppc64le|linux/riscv64|linux/s390x|\
mac/amd64|mac/arm64|\
freebsd/amd64|freebsd/arm64|freebsd/386|freebsd/arm|freebsd/riscv64|\
openbsd/amd64|openbsd/arm64|openbsd/386|openbsd/arm|openbsd/ppc64|openbsd/riscv64|\
android/arm64|\
netbsd/amd64|netbsd/386|netbsd/arm|netbsd/arm64|\
solaris/amd64|illumos/amd64|dragonfly/amd64|aix/ppc64)
;;
*) die "GURL binary is not available for $OS/$ARCH" ;;
esac
URL="$BASE_URL/$OS/$ARCH/gurl"
say "detected platform: $OS/$ARCH"
say "download: $URL"
# Temporary directory
TMPBASE="${TMPDIR:-/tmp}"
TMP="$TMPBASE/gurl-install.$$"
DOWNLOAD="$TMP/gurl"
umask 077
mkdir "$TMP" 2>/dev/null || die "cannot create temporary directory: $TMP"
cleanup() {
rm -rf "$TMP" >/dev/null 2>&1 || true
}
trap cleanup EXIT HUP INT TERM
# Download using the most suitable available tool
download() {
if [ "$OS" = "freebsd" ] || [ "$OS" = "dragonfly" ]; then
if have fetch; then
say "using fetch"
fetch -o "$DOWNLOAD" "$URL" && return 0
fi
fi
if [ "$OS" = "openbsd" ] || [ "$OS" = "netbsd" ]; then
if have ftp; then
say "using ftp"
ftp -o "$DOWNLOAD" "$URL" && return 0
fi
fi
if [ -x /usr/sfw/bin/wget ]; then
say "using /usr/sfw/bin/wget"
/usr/sfw/bin/wget -O "$DOWNLOAD" "$URL" && return 0
fi
if have wget; then
say "using wget"
wget -O "$DOWNLOAD" "$URL" && return 0
fi
if have busybox && busybox wget --help >/dev/null 2>&1; then
say "using BusyBox wget"
busybox wget -O "$DOWNLOAD" "$URL" && return 0
fi
if have toybox && toybox wget --help >/dev/null 2>&1; then
say "using Toybox wget"
toybox wget -O "$DOWNLOAD" "$URL" && return 0
fi
if have curl; then
say "using curl"
curl -fL -o "$DOWNLOAD" "$URL" && return 0
fi
die "no usable HTTP downloader found.
Tried:
fetch
ftp
wget
/usr/sfw/bin/wget
BusyBox wget
Toybox wget
curl
Direct URL:
$URL"
}
download
[ -s "$DOWNLOAD" ] || die "downloaded file is empty"
chmod 755 "$DOWNLOAD" || die "cannot make downloaded GURL executable"
# Root -> /bin, normal user -> ~/.local/bin
IS_ROOT=0
if have id && [ "$(id -u 2>/dev/null)" = "0" ]; then
IS_ROOT=1
fi
if [ "$IS_ROOT" = "1" ]; then
DESTDIR="/bin"
else
[ -n "${HOME:-}" ] || die "HOME is not defined"
DESTDIR="$HOME/.local/bin"
fi
DEST="$DESTDIR/gurl"
mkdir -p "$DESTDIR" || die "cannot create $DESTDIR"
cp "$DOWNLOAD" "$DEST" || die "cannot install $DEST"
chmod 755 "$DEST" || die "cannot chmod $DEST"
say "installed: $DEST"
"$DEST" -V || die "GURL was installed, but version test failed"
# Print immediate help
echo
echo "============================================================"
echo "GURL is ready"
echo "============================================================"
echo
echo "Installed:"
echo " $DEST"
echo
echo "Try it now:"
echo
echo " $DEST https://example.com"
echo
echo "Download a file:"
echo
echo " $DEST -o file.zip https://example.com/file.zip"
echo
if [ "$IS_ROOT" = "1" ]; then
echo "System-wide command:"
echo
echo " gurl https://example.com"
else
case ":${PATH:-}:" in
*":$DESTDIR:"*)
echo "GURL is already in your PATH."
echo
echo "Run:"
echo
echo " gurl https://example.com"
;;
*)
echo "$DESTDIR is not in your PATH yet."
echo
echo "For this shell, run:"
echo
echo " export PATH=\"$DESTDIR:\$PATH\""
echo
echo "Then:"
echo
echo " gurl https://example.com"
echo
echo "To make it permanent, add the export line to your shell profile."
;;
esac
fi
echo
echo "Help:"
echo " gurl --help"
echo
echo "Version:"
echo " gurl -V"
echoChoose your platform and architecture below.
The binary URLs intentionally use HTTP. This is the bootstrap path for old or minimal systems where HTTPS tools, CA certificates, OpenSSL, or the installed TLS stack may be unavailable or obsolete. After downloading GURL, use GURL itself for HTTPS.
Linux
amd64 / arm64 / 386 / ARM / LoongArch / MIPS / PPC64 / RISC-V / s390x
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/amd64/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/amd64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/amd64/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/arm64/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/arm64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/arm64/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/386/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/386/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/386/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/arm/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/arm/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/arm/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/loong64/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/loong64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/loong64/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mipsle/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mipsle/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mipsle/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips64/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips64/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips64le/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips64le/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/mips64le/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/ppc64/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/ppc64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/ppc64/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/ppc64le/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/ppc64le/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/ppc64le/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/riscv64/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/riscv64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/riscv64/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/s390x/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/linux/s390x/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/linux/s390x/gurl; else echo 'No HTTP downloader found (wget, BusyBox wget, or curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
macOS
Intel / Apple Silicon
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; /usr/bin/curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/mac/amd64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; /usr/bin/curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/mac/arm64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
Windows
amd64 / arm64 / 386 / ARM
The command uses System.Net.WebClient, which works with older Windows PowerShell versions and does not require Invoke-WebRequest.
(New-Object System.Net.WebClient).DownloadFile("http://files.zabiyaka.net/gurl/latest/windows/amd64/gurl.exe", "$PWD\gurl.exe"); .\gurl.exe -V(New-Object System.Net.WebClient).DownloadFile("http://files.zabiyaka.net/gurl/latest/windows/arm64/gurl.exe", "$PWD\gurl.exe"); .\gurl.exe -V(New-Object System.Net.WebClient).DownloadFile("http://files.zabiyaka.net/gurl/latest/windows/386/gurl.exe", "$PWD\gurl.exe"); .\gurl.exe -V(New-Object System.Net.WebClient).DownloadFile("http://files.zabiyaka.net/gurl/latest/windows/arm/gurl.exe", "$PWD\gurl.exe"); .\gurl.exe -V
FreeBSD
amd64 / arm64 / 386 / ARM / RISC-V
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; fetch -o "$DEST" http://files.zabiyaka.net/gurl/latest/freebsd/amd64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; fetch -o "$DEST" http://files.zabiyaka.net/gurl/latest/freebsd/arm64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; fetch -o "$DEST" http://files.zabiyaka.net/gurl/latest/freebsd/386/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; fetch -o "$DEST" http://files.zabiyaka.net/gurl/latest/freebsd/arm/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; fetch -o "$DEST" http://files.zabiyaka.net/gurl/latest/freebsd/riscv64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
OpenBSD
amd64 / arm64 / 386 / ARM / PPC64 / RISC-V
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/openbsd/amd64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/openbsd/arm64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/openbsd/386/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/openbsd/arm/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/openbsd/ppc64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/openbsd/riscv64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
Android
arm64
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/android/arm64/gurl; elif command -v toybox >/dev/null 2>&1; then toybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/android/arm64/gurl; elif command -v busybox >/dev/null 2>&1; then busybox wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/android/arm64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/android/arm64/gurl; else echo 'No HTTP downloader found (wget/Toybox/BusyBox/curl).' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
NetBSD
amd64 / 386 / ARM / arm64
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/netbsd/amd64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/netbsd/386/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/netbsd/arm/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; ftp -o "$DEST" http://files.zabiyaka.net/gurl/latest/netbsd/arm64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
Solaris
amd64
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/solaris/amd64/gurl; elif [ -x /usr/sfw/bin/wget ]; then /usr/sfw/bin/wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/solaris/amd64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/solaris/amd64/gurl; else echo 'No HTTP downloader found. Install/copy wget or curl, or use the direct download link above.' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
Plan 9
amd64 / 386 / ARM
Uses Plan 9 hget, whose native purpose is retrieving HTTP URLs.
hget http://files.zabiyaka.net/gurl/latest/plan9/amd64/gurl >gurl
./gurl -V
hget http://files.zabiyaka.net/gurl/latest/plan9/386/gurl >gurl
./gurl -V
hget http://files.zabiyaka.net/gurl/latest/plan9/arm/gurl >gurl
./gurl -V
Illumos
amd64
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/illumos/amd64/gurl; elif [ -x /usr/sfw/bin/wget ]; then /usr/sfw/bin/wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/illumos/amd64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/illumos/amd64/gurl; else echo 'No HTTP downloader found. Install/copy wget or curl, or use the direct download link above.' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
DragonFly BSD
amd64
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; fetch -o "$DEST" http://files.zabiyaka.net/gurl/latest/dragonfly/amd64/gurl && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"
AIX
ppc64
AIX base ftp speaks FTP, not HTTP. Because the GURL bootstrap server here is HTTP, a bare AIX installation needs an available HTTP downloader (wget/curl) or the binary copied from another machine.
if [ "$(id -u 2>/dev/null)" = "0" ]; then DESTDIR="/bin"; else DESTDIR="$HOME/.local/bin"; fi; mkdir -p "$DESTDIR"; DEST="$DESTDIR/gurl"; if command -v wget >/dev/null 2>&1; then wget -O "$DEST" http://files.zabiyaka.net/gurl/latest/aix/ppc64/gurl; elif command -v curl >/dev/null 2>&1; then curl -fL -o "$DEST" http://files.zabiyaka.net/gurl/latest/aix/ppc64/gurl; else echo 'Base AIX ftp does not fetch HTTP URLs. Copy/install wget or curl, or use the direct download link above.' >&2; exit 1; fi && chmod 755 "$DEST" && "$DEST" -V && echo && echo "GURL installed: $DEST" && echo "Run: $DEST https://example.com"Basic syntax:
gurl [options] <URL>
Simple GET request:
gurl https://example.comA URL without a scheme automatically uses HTTP:
gurl example.comEquivalent to:
gurl http://example.comgurl -o file.zip https://example.com/file.zipor:
gurl --output file.zip https://example.com/file.zipgurl https://example.com/script.sh | bashgurl -d "key=value&key2=value2" https://example.comor:
gurl --data "key=value&key2=value2" https://example.comWhen -d / --data is used, GURL automatically performs a POST request.
gurl -H "Content-Type: application/json" -d '{"key":"value"}' https://example.com/apiText fields and files can be supplied in one -F argument separated by &:
gurl -F "name=test&file=@/tmp/file.txt" https://example.com/uploadgurl -X DELETE https://example.com/api/itemgurl -X PUT https://example.com/api/itemgurl -H "Authorization: Bearer TOKEN" https://example.com/apior:
gurl --header "Authorization: Bearer TOKEN" https://example.com/apigurl -b "session_id=abc123" https://example.comor:
gurl --cookie "session_id=abc123" https://example.comgurl -I https://example.comor:
gurl --head https://example.comgurl -A "MyClient/1.0" https://example.comor:
gurl --user-agent "MyClient/1.0" https://example.comgurl -m 10 https://example.comor:
gurl --connect-timeout 10 https://example.com-m / --max-time limits the complete transfer. --connect-timeout limits
connection establishment. Values use curl-compatible seconds and may be
fractional. There is no total transfer timeout by default.
Useful for self-signed certificates:
gurl -k https://192.168.1.1or:
gurl --unsafe https://192.168.1.1Warning: disabling certificate verification reduces connection security.
gurl --fail https://example.com/not-foundFor HTTP status 400 and above, GURL exits with error code 22.
This is useful in shell scripts:
gurl --fail https://example.com/file || echo "Download failed"Like curl, GURL does not follow HTTP redirects by default. Use -L when the
redirect target should be requested:
gurl -L https://example.comgurl -Vor:
gurl --version-s, --silent silent mode
-D, --dump-header <file> write received headers to a file
-4, --ipv4 use IPv4 only
-6, --ipv6 use IPv6 only
-L, --location follow redirects
--trace-ascii <file> write an ASCII request/response trace
--capath <directory> use certificates from a CA directory
--cacert <file> use a CA certificate bundle
-g, --globoff disable URL globbing (GURL never expands it)
-k, --insecure disable TLS certificate verification
-I, --head perform a HEAD request and print headers
-A, --user-agent <name> set User-Agent
-X, --request <method> set the HTTP method
-H, --header <header> add a header; may be repeated
-d, --data <contents> send request data; may be repeated
--connect-timeout <seconds> limit DNS, TCP, and TLS connection time
-m, --max-time <seconds> limit the complete transfer
-o, --output <file> save the response body
-f, --fail return exit code 22 for HTTP errors
-F, --form <field> send a multipart field or field=@file
-b, --cookie <cookies> send the Cookie header
-V, --version show GURL version
The historical --useragent, --unsafe, and duration-based --timeout names
remain available for existing GURL scripts. Curl-compatible names should be
used in new scripts.
GURL accepts the complete curl option set emitted by acme.sh 3.1.5. The binary
may be copied or linked under the name curl; no wrapper or argument translation
is required:
install -m 0755 gurl /usr/local/bin/curl
curl --silent --dump-header /root/.acme.sh/http.header -L \
--connect-timeout 10 --user-agent 'acme.sh/3.1.5' \
-H '' https://acme.zerossl.com/v2/DV90The embedded CA file is the Mozilla bundle published at
https://curl.se/docs/caextract.html, revision 2026-08-13, SHA-256
f66dff1bdf8f96060b8177976f8b7d9254bc89bc4db933d769f7384d28480bc9.
It is distributed under MPL 2.0. --cacert or --capath replaces the embedded
trust roots for that invocation. --insecure remains explicit and should only
be used for controlled diagnostics.
To update the built-in roots, download a new cacert.pem from that source into
pkg/certificates, verify it against the published .sha256 file, then update
the pinned checksum and root count in pkg/certificates/certificates_test.go
and this section. Run go test ./... before publishing binaries.
Clone the repository:
git clone https://github.com/matveynator/gurl.git
cd gurlBuild:
go build -o gurl gurl.goRun:
./gurl https://example.comRun the complete test suite, race detector, and coverage report:
go test -count=1 -race -coverprofile=coverage.out ./...
go tool cover -func=coverage.outThe same checks run in GitHub Actions. Coverage reports are published to Coveralls.
Release binaries can be cross-compiled with the standalone release utility:
go run scripts/crosscompile/crosscompile.goGURL is distributed under the GNU General Public License v3.0. The embedded Mozilla CA bundle is separately distributed under MPL 2.0.
https://github.com/matveynator/gurl
Contributions and fixes are welcome.
