HTTP Request Runner: Bulk API Calls & Checks avatar

HTTP Request Runner: Bulk API Calls & Checks

Pricing

from $0.80 / 1,000 http requests

Go to Apify Store
HTTP Request Runner: Bulk API Calls & Checks

HTTP Request Runner: Bulk API Calls & Checks

Send a batch of HTTP requests and API calls (GET, POST, PUT, PATCH, DELETE) with headers, JSON body and query. Fill URLs from variables or CSV. Get status, response time, headers, parsed JSON and redirects, with retries, checks and hidden secrets.

Pricing

from $0.80 / 1,000 http requests

Rating

0.0

(0)

Developer

Malik Said

Malik Said

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

14 hours ago

Last modified

Share

HTTP Request Runner sends a batch of HTTP requests and API calls that you define. Each request can use any common method, headers, a query and a JSON or text body. The Actor saves one record per request with the status, response time, headers, the body (parsed when it is JSON) and every redirect. Use it from Clay, n8n, Make, Zapier, an AI agent or the Apify API.

What HTTP Request Runner does

  • Sends GET, POST, PUT, PATCH, DELETE, HEAD and OPTIONS requests.
  • Fills URLs, headers, query and body from rows of variables. Rows can come from a JSON list, CSV text or another Apify dataset.
  • Retries network errors, timeouts and busy answers (408, 425, 429, 500, 502, 503, 504) up to 2 times.
  • Parses JSON answers and picks values with simple paths such as data.items[0].id.
  • Checks each answer: status, text in the body, JSON values, headers and response time.
  • Keeps API keys and tokens in an encrypted Secrets field. Their values never appear in the results or the log.
  • Follows up to 10 redirects and lists each hop.
  • Respects robots.txt on every host and every redirect. Disallowed paths are not sent and cost nothing.

HTTP request output: what you get

One record per request. Main fields:

FieldMeaning
index, labelOrder of the request and your own label
method, urlWhat was sent, with variables filled
okTrue for a 2xx answer with no error
status, statusTextStatus of the final answer, or robots-disallowed
timeMs, firstByteMsResponse time and time to first byte, in milliseconds
attemptsTries made, including retries
redirects, finalUrlEach redirect hop and the final URL
responseHeaders, contentTypeHeaders of the final answer
jsonParsed body when the answer is JSON
bodyBody as text when it is not JSON
bodyType, bodyBytes, bodyTruncatedjson, text, binary or empty; size kept; whether it was cut
extractedValues picked with Values to pick
assertionsPassed, assertionFailuresResult of your checks
errorWhy a request failed or was refused
callbackStatusStatus your callback URL answered for this record. Null when no callback is set

Binary answers such as images and PDFs are not saved. Their size and headers are. A body longer than Maximum body size is cut and marked bodyTruncated. A cut body is not parsed as JSON.

Sample record from a test run (the POST example in the input form; some response headers left out):

{
"id": "request-00001",
"index": 1,
"label": "create",
"variables": null,
"method": "POST",
"url": "https://jsonplaceholder.typicode.com/posts",
"requestHeaders": {
"Content-Type": "application/json",
"User-Agent": "Mozilla/5.0 (compatible; http-request-runner/0.1; Apify Actor)",
"Accept": "application/json, text/plain, */*",
"Accept-Encoding": "gzip, deflate, br"
},
"requestBodyBytes": 47,
"ok": true,
"status": 201,
"statusText": "Created",
"finalUrl": "https://jsonplaceholder.typicode.com/posts",
"redirects": [],
"attempts": 1,
"timeMs": 227,
"firstByteMs": 227,
"responseHeaders": {
"content-type": "application/json; charset=utf-8",
"content-length": "73",
"location": "https://jsonplaceholder.typicode.com/posts/101",
"server": "cloudflare"
},
"contentType": "application/json; charset=utf-8",
"bodyBytes": 73,
"bodyTruncated": false,
"bodyType": "json",
"body": null,
"json": { "title": "Hello", "body": "Test post", "userId": 1, "id": 101 },
"extracted": null,
"assertionsPassed": true,
"assertionFailures": [],
"error": null,
"requestedAt": "2026-10-22T08:08:10.203Z",
"callbackStatus": null,
"scrapedAt": "2026-10-22T08:08:10.432Z"
}

How to send bulk HTTP requests

  1. Open the input form. Add your calls in Requests, or paste plain URLs in URLs.
  2. Put tokens and API keys in Secrets, one per line, as NAME=value.
  3. Use {{secret.NAME}} where the key goes, for example in a header: "Authorization": "Bearer {{secret.API_TOKEN}}".
  4. To call one endpoint for many records, write {{name}} in the URL or body. Then add rows in Variables, Variables as CSV or Variables from a dataset.
  5. Add Checks for every response if you want a pass or fail per request.
  6. Run the Actor. Read the results in the Overview table, or as JSON, CSV or Excel.

Example request list:

[
{
"label": "post",
"method": "GET",
"url": "https://jsonplaceholder.typicode.com/posts/{{postId}}",
"extract": { "title": "title", "userId": "userId" }
},
{
"label": "create",
"method": "POST",
"url": "https://jsonplaceholder.typicode.com/posts",
"headers": { "Content-Type": "application/json" },
"body": { "title": "Hello", "body": "Test post", "userId": 1 },
"expect": { "status": "201", "json": { "title": "Hello" } }
}
]

With Variables [{"postId": 1}, {"postId": 2}], the first request runs twice and the second runs once.

Same body for a list of URLs

You do not need the full Requests list to send one body to many URLs. Paste the URLs in URLs, set Method to POST, and put the JSON in Body. Add shared Query parameters the same way.

{
"urls": ["https://jsonplaceholder.typicode.com/posts", "https://jsonplaceholder.typicode.com/comments"],
"method": "POST",
"query": { "source": "apify" },
"body": { "title": "Hello", "token": "{{secret.API_TOKEN}}" }
}

Each URL gets one request with the same query and body. Secrets in the body are filled when sent and hidden in the results. GET and HEAD requests send no body; the log says so.

Template rules

  • {{name}} in a URL is URL-encoded. {{{name}}} is inserted as written, for example a full base URL.
  • In a JSON body, a value that is only "{{id}}" keeps the variable's type, so a number stays a number.
  • {{user.name}} reads a nested field from the row.
  • CSV values are always text.
  • A request whose variable is missing in a row is refused and not charged.

Checks and picked values

expect keys: status ("2xx", "200", "200,201" or "200-299"), bodyContains, bodyNotContains, maxTimeMs, json and headerContains. In json, map a path to the value you expect, or to "*" to require only that the path exists.

extract maps a name to a path: data.id, items[0].name, items[-1].name (last item), items[*].id (all items) or header:etag.

Input

OptionDefaultMeaning
RequestsExampleFull request list (method, url, headers, query, body, label, expect, extract)
URLsNoneQuick list, sent with Method and the shared Headers, Query parameters and Body
MethodGETMethod for the URLs list
HeadersNoneHeaders added to every request
Query parametersNoneQuery parameters added to every URL in the URLs list
BodyNoneJSON body sent with every URL in the URLs list. GET and HEAD send no body
SecretsNoneNAME=value lines, encrypted, used as {{secret.NAME}}
VariablesExampleRows that fill {{placeholders}}
Variables as CSVNoneSame, as CSV text
Variables from a datasetNoneSame, from an Apify dataset
Checks for every responseNoneChecks applied to every answer
Values to pickNonePaths picked from every JSON answer
Maximum requests100Stop after this many. 0 means the limit of 5,000
Parallel requests5Up to 10 at once across hosts
Delay per host (ms)250Gap between two requests to one host. At least 200
Timeout per request30 sUp to 60 s
Retries2Up to 2
Follow redirectsOnUp to 10 hops
Maximum body size256 KBUp to 1,024 KB
Callback URLNonePOST each result record as JSON to your webhook
Mark the run failed when a request failsOffThe run ends as failed after saving every result, so a run-failed alert fires

An empty input runs the example from the input form.

robots.txt rule

The Actor reads robots.txt for every host, and again for every redirect hop. It follows the rules for all crawlers (User-agent: *). The check always runs. You cannot turn it off.

  • A path that robots.txt disallows is not sent. Its row has status set to robots-disallowed, and it costs nothing.
  • The rule applies to every method, because robots.txt has no method rules.
  • A site with no robots.txt (404) is allowed.
  • A robots.txt that cannot be read (server error or no connection) blocks the host, as RFC 9309 requires.
  • Some APIs disallow all crawlers in robots.txt. This Actor cannot call them.

Limits and safety

The Actor is for API calls and checks. It is not a load testing tool. These limits are fixed:

  • At most 5,000 requests per run and 2,000 per host.
  • At most 2 requests at a time to one host, and at least 200 ms between them.
  • The default run timeout is 3,600 s (1 hour). The run stops sending about 45 s before the timeout, so every saved row is kept.
  • Request bodies up to 1 MB. Response bodies kept up to 1 MB.
  • Private, local and cloud metadata addresses are refused, also after DNS lookup and after redirects.
  • Ports below 1024 are refused, except 80 and 443.
  • Usernames and passwords inside URLs are refused. Use Secrets.
  • Headers that hold a secret, plus Authorization and Cookie, are dropped when a redirect goes to another host.

You choose the endpoints. Follow each API's terms and rate limits. The Actor uses no proxy and does not get around logins, CAPTCHAs or bot protection.

Pricing

You pay a small start fee per run and a fee per request sent. Requests refused before sending (bad URL, private address, missing variable, robots.txt disallow) are saved with the reason and cost nothing. Retries of one request count as one request.

EventFree planGOLD plan and higher
Run start$0.001$0.001
HTTP request$0.001 ($1.00 per 1,000)$0.0008 ($0.80 per 1,000)
HTTP requests in one runFree planGOLD plan and higher
100$0.101$0.081
1,000$1.001$0.801

Costs include the run start fee.

FAQ

Can I call an API that needs a key? Yes. Put the key in Secrets and use {{secret.NAME}} in a header, the query or the URL.

Can I chain it after another Actor? Yes. Pick that Actor's dataset in Variables from a dataset. Each item becomes one row of variables.

Does it parse XML or HTML? It returns them as text in body. Only JSON is parsed.

Why was my request refused? The error field says why. A status of robots-disallowed means the site's robots.txt does not allow that path.

How do I get notified when a check fails? Turn on Mark the run failed when a request fails and add Apify's run-failed alert or webhook. Every result is still saved first. To get each result as it arrives, set Callback URL to your n8n, Make or Zapier webhook.

Other Actors by the same developer

Support

Report a problem in the Issues tab. Include the run link. Never paste a secret in an issue.