How to Set Up Smartproxy Proxies on Linux with curl and Python for CLI Automation
Route curl and Python traffic through Smartproxy residential or datacenter proxies on Linux, verify your exit IP, pin sticky sessions, and schedule recurring checks with cron or systemd.
Overview
This tutorial shows how to send command-line and Python traffic through a proxy on Linux, including authentication, exit-IP verification, session pinning, and scheduled runs. Smartproxy is used here as the suggested provider because it offers residential and datacenter proxies over HTTP and SOCKS5 with flat monthly billing and a 65M+ IP pool, but every step works with any proxy service that exposes the same protocols.
By the end of this guide you will be able to:
- Authenticate to your proxy endpoint from the shell with
curl - Confirm that outbound traffic exits from the proxy IP rather than your own
- Use the same endpoint from Python with
requests - Pin a sticky session or rotate IPs between requests
- Automate health checks with cron or a systemd timer
Prerequisites
- A Linux host (commands below use Debian/Ubuntu; Fedora and Arch equivalents are noted)
curland Python 3.8 or newer- A Smartproxy account with an active plan and proxy credentials
- The endpoint host and ports for the product you want to use, copied from the dashboard inside your Smartproxy account
- Outbound access on the proxy port, and no corporate firewall or VPN client that blocks it
Step 1 — Install the required tools
Install curl and Python, then create an isolated environment for the Python client.
sudo apt update
sudo apt install -y curl python3 python3-venv
On Fedora or RHEL-based systems use:
sudo dnf install -y curl python3
Create a virtual environment and install the HTTP client plus SOCKS support:
python3 -m venv ~/.venvs/proxy
source ~/.venvs/proxy/bin/activate
pip install --upgrade pip
pip install 'requests[socks]'
The requests[socks] extra pulls in PySocks, which is what makes socks5h:// URLs work in Python.
Step 2 — Store credentials outside your scripts
Hard-coding credentials into scripts or committing them to a repository is the most common way proxy accounts leak. Keep them in a single file with restrictive permissions and load it only when needed.
install -d -m 700 ~/.config/smartproxy
install -m 600 /dev/null ~/.config/smartproxy/env
Open the file in your editor and replace each placeholder with the values shown in your provider dashboard:
# ~/.config/smartproxy/env
# Replace every REPLACE_WITH_ value using the endpoint and credentials
# from your provider dashboard. Do not commit this file to version control.
export SP_PROXY_HOST="REPLACE_WITH_ENDPOINT_HOST"
export SP_PROXY_PORT_HTTP="REPLACE_WITH_HTTP_PORT"
export SP_PROXY_PORT_SOCKS5="REPLACE_WITH_SOCKS5_PORT"
export SP_PROXY_USER="REPLACE_WITH_PROXY_USERNAME"
export SP_PROXY_PASS="REPLACE_WITH_PROXY_PASSWORD"
Load the variables into your current shell:
set -a; . ~/.config/smartproxy/env; set +a
If you use both residential and datacenter products, keep a separate variable pair for each, because they usually have different hosts or ports.
Step 3 — Choose between HTTP and SOCKS5
Both protocols are supported by Smartproxy, and the right choice depends on what you are sending through the tunnel.
| Traffic type | Recommended protocol | Why |
|---|---|---|
HTTPS requests from curl, requests, or scrapers |
HTTP proxy (CONNECT tunnel) | Simplest to configure, works with every HTTP client, and passes the destination hostname to the proxy |
| Non-HTTP traffic such as SSH, SMTP, or custom TCP clients | SOCKS5 | Protocol-agnostic, forwards arbitrary TCP streams |
| Tools that cannot handle proxy authentication natively | SOCKS5 | Credentials are handled by the client library rather than the target tool |
| Maximum client compatibility | HTTP | Universally supported by HTTP libraries and most CLI tools |
If you only ever fetch HTTPS URLs, start with HTTP and switch to SOCKS5 only if a tool requires it.
Step 4 — Test the connection with curl
Send a request through the HTTP proxy and print the exit IP that the destination sees:
curl -sS --max-time 30 \
--proxy "http://${SP_PROXY_HOST}:${SP_PROXY_PORT_HTTP}" \
--proxy-user "${SP_PROXY_USER}:${SP_PROXY_PASS}" \
'https://api.ipify.org?format=json'
Now test the same endpoint over SOCKS5. The --socks5-hostname variant resolves DNS at the proxy, which prevents local DNS lookups from leaking your real location:
curl -sS --max-time 30 \
--socks5-hostname "${SP_PROXY_HOST}:${SP_PROXY_PORT_SOCKS5}" \
--proxy-user "${SP_PROXY_USER}:${SP_PROXY_PASS}" \
'https://api.ipify.org?format=json'
Compare the result with a direct request that bypasses the proxy entirely:
curl -sS 'https://api.ipify.org?format=json'
If the proxied IP differs from the direct IP, traffic is exiting through the proxy. Run the proxied command a few times to see whether the exit IP changes; that tells you whether you are on a rotating or sticky endpoint.
Step 5 — Pin a sticky session or rotate on every request
Rotating behaviour is the default on most residential endpoints: each new connection may leave through a different IP. For logins, multi-step forms, or checkout-style flows you usually want the same IP for a whole sequence of requests.
Your provider builds sticky usernames from a session token. Append the token to the proxy username using the exact pattern shown in the session generator in your dashboard, which commonly looks like a suffix on the username:
export SP_SESSION_ID="$(openssl rand -hex 4)"
export SP_SESSION_USER="${SP_PROXY_USER}-session-${SP_SESSION_ID}"
Then substitute $SP_SESSION_USER wherever the commands above use $SP_PROXY_USER. Reuse the same token for the duration of the task, and generate a new token when you want a fresh exit IP.
| Goal | Approach |
|---|---|
| Collect many independent pages | Default rotating username, one request per connection |
| Keep a login or cart intact | Reuse one session token for the whole workflow |
| Distribute load across a region | Use the same session token with a fixed country or city if your plan exposes those options in the dashboard |
| Isolate parallel workers | Give each worker process its own randomly generated session token |
Step 6 — Use the proxy from Python
With the environment file loaded, the same variables are available to Python. This example uses the HTTP proxy for an HTTPS request:
import os
from urllib.parse import quote
import requests
host = os.environ['SP_PROXY_HOST']
port = os.environ['SP_PROXY_PORT_HTTP']
user = quote(os.environ['SP_PROXY_USER'], safe='')
password = quote(os.environ['SP_PROXY_PASS'], safe='')
proxies = {
'http': f'http://{user}:{password}@{host}:{port}',
'https': f'http://{user}:{password}@{host}:{port}',
}
response = requests.get(
'https://api.ipify.org?format=json',
proxies=proxies,
timeout=30,
)
response.raise_for_status()
print(response.json())
To switch to SOCKS5, change only the scheme and port. The socks5h scheme performs remote DNS resolution, matching curl --socks5-hostname:
socks_port = os.environ['SP_PROXY_PORT_SOCKS5']
socks_proxies = {
'http': f'socks5h://{user}:{password}@{host}:{socks_port}',
'https': f'socks5h://{user}:{password}@{host}:{socks_port}',
}
Two practical notes:
- Always set an explicit
timeout. Proxy networks are large and individual exit nodes can be slow or unavailable, and a missing timeout turns a bad node into a hung process. - Percent-encode the username and password, as shown with
quote(), because session delimiters and special characters break proxy URLs if they are passed through raw.
A small retry wrapper makes scripts far more resilient:
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
session.proxies.update(proxies)
session.mount('https://', HTTPAdapter(max_retries=Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
)))
Step 7 — Run the check on a schedule
Save the verification snippet as ~/scripts/check_proxy.py, then schedule it with cron so credential problems and dead endpoints surface early.
# Rotate a log of exit IPs every hour
0 * * * * set -a; . $HOME/.config/smartproxy/env; set +a; $HOME/.venvs/proxy/bin/python $HOME/scripts/check_proxy.py >> $HOME/proxy-check.log 2>&1
The same job as a systemd service and timer, which is easier to monitor with journalctl:
# ~/.config/systemd/user/proxy-check.service
[Unit]
Description=Verify proxy exit IP
[Service]
Type=oneshot
EnvironmentFile=%h/.config/smartproxy/env
ExecStart=%h/.venvs/proxy/bin/python %h/scripts/check_proxy.py
# ~/.config/systemd/user/proxy-check.timer
[Unit]
Description=Run the proxy check hourly
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
Enable and start it with:
systemctl --user daemon-reload
systemctl --user enable --now proxy-check.timer
systemctl --user list-timers proxy-check.timer
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
407 Proxy Authentication Required |
Wrong username or password, or special characters not URL-encoded | Re-copy credentials from the dashboard and percent-encode them with quote() in Python |
curl: (5) Could not resolve proxy |
Host variable is empty or misspelled | Run echo "$SP_PROXY_HOST" and re-source the env file |
curl: (7) Failed to connect or a timeout |
Port blocked by a firewall, VPN, or the wrong port for the product | Confirm the port in the dashboard and test it with nc -zv "$SP_PROXY_HOST" "$SP_PROXY_PORT_HTTP" |
curl: (56) CONNECT tunnel failed |
The exit node dropped the connection or the destination rejected the request | Retry, and reduce concurrency if it happens constantly |
Requests work in a browser but fail in curl over SOCKS5 |
Local DNS resolution | Add --socks5-hostname instead of --socks5 |
Python raises Missing dependencies for SOCKS support |
PySocks is not installed | Activate the venv and run pip install 'requests[socks]' |
| Exit IP never changes | You are reusing a sticky session token | Generate a new session ID for each worker |
| Exit IP equals your own IP | Proxy variables were not loaded, or a tool bypassed the proxy | Re-source the env file and re-run the direct-versus-proxied comparison |
Additional checks worth running when something behaves unexpectedly:
- Print the resolved variables with
env | grep SP_PROXYto rule out shell-scoping mistakes. - Test both protocols; if SOCKS5 works and HTTP does not, the issue is with the client configuration rather than the endpoint.
- Log the exit IP alongside the timestamp in your job output so you can correlate failures with specific nodes.
Summary
- Smartproxy exposes residential and datacenter proxies over HTTP and SOCKS5 with flat monthly billing, which makes it a reasonable suggested provider for CLI and scripting workflows.
- Keep credentials in a
chmod 600environment file and load them withset -a; . file; set +ainstead of embedding them in scripts. - Use the HTTP proxy for HTTPS-only tooling and
--socks5-hostnameorsocks5h://when you need protocol-agnostic forwarding or remote DNS resolution. - Verify setup by comparing a proxied request to a direct one; matching IPs mean the proxy was bypassed.
- Append a session token to the username for sticky workflows, and generate a new token per worker for parallel rotating jobs.
- Wire the same check into cron or a systemd timer so credential expiry and dead endpoints are noticed before a production run fails.