← Blog · · 4 min read

How to Test a Residential Proxy with cURL Before You Scale

A proxy should be tested as a system, not judged by one successful request. Before connecting a scraper, browser, or data pipeline, verify the endpoint, credentials, observed exit, targeting behavior, connection reuse, and failure handling from the environment that will run the workload.

cURL is ideal for this first pass because it exposes proxy configuration clearly and produces reproducible commands. The examples below use PacketStream’s recommended HTTPS endpoint and ipinfo.io as an inspection target.

Keep credentials out of the command itself

Start by placing temporary shell variables in your current session. Use your real PacketStream username and auth key, but do not commit them to a script or shell history file.

read -r -p 'PacketStream username: ' PACKETSTREAM_USER
read -r -s -p 'PacketStream auth key: ' PACKETSTREAM_AUTH_KEY
printf '\n'
export PACKETSTREAM_USER PACKETSTREAM_AUTH_KEY

The variables disappear when that shell session ends unless you deliberately persist them.

Send a request through proxy.packetstream.io on port 31111:

curl --silent --show-error --fail-with-body \
  --proxy 'https://proxy.packetstream.io:31111' \
  --proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}" \
  'https://ipinfo.io' \
  | jq '{ip, hostname, city, region, country, loc, org, postal, timezone}'

A successful result confirms that cURL can reach the proxy, authenticate, connect to the destination, and return structured exit information. It does not yet prove that every application setting is correct.

Check that:

  • ip differs from the direct connection you expected to replace;
  • country matches any country target you requested;
  • the response is valid JSON rather than an HTML error page;
  • no credential appears in logs, screenshots, or copied output.

IP geolocation is approximate. City and region fields can be useful diagnostic hints, but country is the supported targeting boundary.

Capture status and timing separately

Do not mix response data with cURL’s diagnostics. Write the body to a file and emit a small metrics record to standard output:

curl --silent --show-error \
  --output /tmp/packetstream-ipinfo.json \
  --write-out '{"http_code":%{http_code},"connect_seconds":%{time_connect},"total_seconds":%{time_total}}\n' \
  --proxy 'https://proxy.packetstream.io:31111' \
  --proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}" \
  'https://ipinfo.io'

jq '{ip, country, org}' /tmp/packetstream-ipinfo.json

Treat timing as an observation from your machine at that moment, not as a universal performance promise. Repeat the test from the deployment region and with a representative destination before setting timeouts.

Test country targeting

Append a two-letter ISO code to the auth key. This example asks for a United States exit:

curl --silent --show-error --fail-with-body \
  --proxy 'https://proxy.packetstream.io:31111' \
  --proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}_country-US" \
  'https://ipinfo.io' \
  | jq '{ip, country, region, city}'

Assert that the returned country is US. If the selected country has no exits available, PacketStream fails the request rather than falling back to another location. Your application should preserve that distinction instead of accepting an unexpected country.

Test rotation with new connections

PacketStream selects a residential exit for each new proxy connection. To make the connection boundary explicit in cURL, use --no-keepalive and run separate processes:

for attempt in 1 2 3 4 5; do
  curl --silent --show-error --fail-with-body \
    --no-keepalive \
    --proxy 'https://proxy.packetstream.io:31111' \
    --proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}" \
    'https://ipinfo.io' \
    | jq -r '[.ip, .country, .org] | @tsv'
done

This is a behavioral check, not a demand that every small sample contain five distinct IPs. Record what the network returns and design the real client with a clear connection-pooling policy.

Test a sticky session

Append a non-sensitive session ID and repeat the request:

SESSION_ID='curlcheck42'

for attempt in 1 2 3; do
  curl --silent --show-error --fail-with-body \
    --proxy 'https://proxy.packetstream.io:31111' \
    --proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}_session-${SESSION_ID}" \
    'https://ipinfo.io' \
    | jq -r '.ip'
done

PacketStream sticky sessions can retain the same exit for up to 60 minutes. If the associated Packeter disconnects, the session fails. A production integration therefore needs a deliberate policy for restarting a stateful workflow with a new session.

Test SOCKS5 when needed

For a SOCKS5 client, use the PacketStream endpoint on port 31113:

curl --silent --show-error --fail-with-body \
  --proxy 'socks5h://proxy.packetstream.io:31113' \
  --proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}" \
  'https://ipinfo.io' \
  | jq '{ip, country, org}'

Verify failure cases before scaling

A useful test plan includes controlled failures:

  • an invalid username or auth key should produce an authentication failure;
  • an unavailable country should not return an exit from another country;
  • an unreachable destination should stop at a bounded timeout;
  • a failed sticky session should not silently become a different identity mid-workflow.

Set --connect-timeout and --max-time to values informed by your application, then make sure the calling process handles nonzero cURL exit codes.

Turn the checklist into an integration test

Once the commands behave correctly, translate the same assertions into the language and HTTP library used by your application. Verify the proxy scheme, endpoint, authentication, expected country, and timeout behavior in CI without printing secrets.

The goal is not merely to see one successful IP response. It is to make the residential proxy behavior observable enough that a configuration mistake fails early—before it becomes an expensive scraping run.