ScreenshotNeo

BlogHow-to

How to Extract cURL Requests from Safari

Copy any Safari network request as cURL on macOS, inspect iPhone traffic, replay it safely, and fix common capture and authentication errors.

By the ScreenshotNeo team1 October 20267 min read

Short answer: Open Safari Web Inspector, select the Network tab, reproduce the action, right-click the matching request, and choose Copy as cURL. On iPhone or iPad, enable Web Inspector on the device, connect it to a Mac, then inspect the mobile page from Safari’s Develop menu.

Safari only records requests after Web Inspector opens. If navigation clears the list, enable Preserve Log before reproducing the action. Treat copied cookies, authorization headers, CSRF tokens, and signed parameters as secrets.

Copy a Safari request as cURL on macOS

1. Enable Safari developer features

  1. Open Safari and choose Safari > Settings > Advanced.
  2. Enable the option to show features for web developers.

Apple documents Web Inspector as the tool for inspecting and debugging HTML, CSS, and JavaScript. You can also open it with Option–Command–I. See Apple’s Web Inspector documentation.

2. Open the Network tab before generating the request

  1. Open the page or web app in Safari.
  2. Choose Develop > Show Web Inspector.
  3. Select Network.
  4. Reload the page or repeat the action that should create the request.

The Network tab lists resources requested since Web Inspector opened, including document loads, XHR, fetch, WebSocket, and navigator.sendBeacon traffic. If a navigation would clear earlier entries, turn on Preserve Log. WebKit’s Network Tab reference describes this behavior.

3. Find the request

Use the filter field and resource-type filters to narrow the list. For an API call, look for fetch or XHR and inspect:

  • Request URL and query string
  • HTTP method, such as GET, POST, or PUT
  • Request headers, especially Authorization, Content-Type, Origin, and Referer
  • Cookies and other session state
  • Form data or a JSON request body
  • Response status and timing

4. Copy it as cURL

Select the request, open its context menu, and choose Copy as cURL. WebKit tracks this command as the feature that creates a cURL representation of the selected request. Paste the result into a text editor first so you can inspect and redact it before running it.

curl 'https://api.example.com/items?limit=20' \\
  -H 'accept: application/json' \\
  -H 'authorization: Bearer REDACTED_TOKEN' \\
  -H 'cookie: session=REDACTED_SESSION' \\
  --compressed

Inspect Safari traffic from an iPhone or iPad

  1. On the iPhone or iPad, open Settings > Apps > Safari > Advanced.
  2. Enable Web Inspector.
  3. Connect the device to a Mac with a cable. After initial setup, Apple also documents using a network connection.
  4. On the Mac, open Safari’s Develop menu, choose the connected device, and select the target webpage.
  5. In the Web Inspector window, select Network.
  6. Reproduce the action on the device, select the request, and choose Copy as cURL.

Apple’s WebKit instructions for enabling Web Inspector explain the device connection. The same capture rules apply: requests made before the inspector opened are not necessarily present, and Preserve Log helps across navigations.

Replay and inspect the copied command

Run the command in a shell only after checking that it does not expose live credentials in your terminal history or logs.

Useful cURL flags

Flag Purpose
-v Show request and response details while troubleshooting.
-i Include response headers in the output.
-o response.bin Save a binary response such as an image or PDF.
--data-raw '...' Send the captured request body without shell interpretation.
--compressed Ask for compressed content and decompress it automatically.
--cookie 'name=value' Send selected cookies without copying the complete Cookie header.
--fail-with-body Return a failing exit code while preserving an error response body.
curl --fail-with-body -v \\
  'https://api.example.com/items' \\
  -H 'accept: application/json' \\
  -H 'authorization: Bearer REDACTED_TOKEN' \\
  -o response.json

Run the same request in Python

Translate the copied method, URL, headers, query parameters, and body explicitly. Avoid sending browser-only headers unless the service requires them.

import requests

url = "https://api.example.com/items"
headers = {
    "accept": "application/json",
    "authorization": "Bearer REDACTED_TOKEN",
}
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
print(response.json())

Run it in Node.js

Modern Node.js versions provide a global fetch.

const res = await fetch('https://api.example.com/items', {
  headers: {
    accept: 'application/json',
    authorization: 'Bearer REDACTED_TOKEN'
  }
});

if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
console.log(await res.json());

POST, JSON, multipart, and authenticated requests

JSON POST

curl 'https://api.example.com/items' \\
  -X POST \\
  -H 'content-type: application/json' \\
  -H 'authorization: Bearer REDACTED_TOKEN' \\
  --data-raw '{"name":"example","enabled":true}'

Form submission

curl 'https://api.example.com/login' \\
  -X POST \\
  -H 'content-type: application/x-www-form-urlencoded' \\
  --data-urlencode 'email=user@example.com' \\
  --data-urlencode 'password=REDACTED'

Multipart upload

curl 'https://api.example.com/upload' \\
  -X POST \\
  -H 'authorization: Bearer REDACTED_TOKEN' \\
  -F 'file=@./report.pdf' \\
  -F 'description=Quarterly report'

Copied commands can include short-lived cookies, CSRF tokens, nonce values, device identifiers, or request signatures. A command that worked in Safari may fail later because the session expired or the server checks browser state. Reproduce the request and copy a fresh command when necessary.

Common problems and fixes

Problem Likely cause Fix
No requests appear Web Inspector opened after the traffic occurred. Open Inspector first, then reload or repeat the action.
The list disappears after navigation Navigation cleared the Network log. Enable Preserve Log before reproducing the flow.
You cannot find the API call The list contains many static assets. Filter by XHR or fetch, then search the request URL or endpoint name.
Copy as cURL is unavailable No request is selected, or the context menu was opened in the wrong pane. Select a row in Network, then use its request context menu.
401 or 403 after replay Expired cookies, authorization, CSRF, origin checks, or anti-bot rules. Capture a fresh request, keep required headers, and use the service’s supported API authentication.
400 or 415 response Missing body, wrong method, or incorrect Content-Type. Compare the copied method, body, query string, and Content-Type byte for byte.
Redirect loop The copied Host, Origin, Referer, or cookies do not match the new environment. Follow redirects with -L only when appropriate and remove browser-only headers one at a time.
iPhone is missing from Develop Web Inspector is disabled, the device is not trusted, or the connection is unavailable. Enable Web Inspector, unlock and trust the Mac, reconnect, and reopen Safari’s Develop menu.
Response is unreadable The endpoint returned compressed or binary data. Use --compressed for compressed responses and -o to save binary output.

Security checklist before sharing a copied command

  • Replace bearer tokens, API keys, session cookies, passwords, and signed URLs with placeholders.
  • Remove personal identifiers and private query parameters.
  • Do not paste secrets into issue trackers, chat rooms, shell history, or public documentation.
  • Prefer a limited-scope test account when replaying requests.
  • Check whether the request performs a write, purchase, deletion, or other irreversible action before running it.
  • Use the service’s documented API when one exists instead of automating an undocumented browser endpoint.

Capture timing, reliability, and performance

Web Inspector records requests generated after it opens, so capture setup is part of the workflow. For multi-step pages, open Inspector before login or navigation, enable Preserve Log, and reproduce the exact user action. Filtering after capture is faster than repeatedly reloading a page.

Replay speed depends on the endpoint, authentication, redirects, payload size, and server-side rate limits. Keep a timeout in scripts, check status codes, and save response bodies when debugging. A copied browser request is a snapshot of one session, not a guarantee that the same command will remain valid.

Or skip the browser setup

If your goal is a clean image or PDF of a page rather than debugging its network traffic, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns PNG, JPEG, WebP, or PDF. Its capture flow accepts cookie and consent banners, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and lets you turn each step off.

Only clean shots are billed: bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing result. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

See the ScreenshotNeo API documentation for all options. This is a runnable cURL request:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same call in Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

And Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Every plan includes the features: full-page and element capture, device presets, custom viewports, retina scale, dark mode, waits, custom CSS and JavaScript, request blocking, headers, cookies, user agents, geolocation, transparent backgrounds, resizing, caching, signed links, async webhooks, bulk capture, usage data, and PDF controls. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Does Safari copy every request as cURL?

It can copy the selected request shown in Web Inspector. WebSocket conversations and browser-managed behavior may need separate interpretation, and replay can depend on session state.

Can I copy a request from Safari on iOS without a Mac?

The documented workflow uses Safari Web Inspector on a connected Mac. Enable Web Inspector on the iPhone or iPad, then select the device from the Mac’s Develop menu.

Why does the copied command contain so many headers?

Safari preserves headers needed to describe the browser request. Start by keeping authentication, content type, origin, and cookies, then remove headers experimentally when building a maintainable client.

Is a copied cURL command safe to publish?

Not until secrets and private data are removed. Cookies, authorization values, signed URLs, and request bodies can grant access or reveal user information.