# Changelog of Bulk HTTP Request Runner (API Caller) (`fecklesspleb/bulk-http-request`) Actor

- **URL**: https://apify.com/fecklesspleb/bulk-http-request/changelog.md
- **Full Actor documentation**: https://apify.com/fecklesspleb/bulk-http-request.md

## Changelog

### Unreleased: invalid input no longer crashes (2026-11-04, local, not built or pushed; based on cloud build 1.0.5)

- **Fix:** input that is not a JSON object (a string, number, `null` or list) crashed the run with exit 91. It now takes the Actor's existing invalid-input path: exit 0, one free status row (`status: error`, message `Not charged: the input is invalid (the input must be a JSON object, got <type>.) ...`), no `RUN_SUMMARY`, no charged event.
- **Fix:** wrong-type values that crashed with exit 91 before anything was sent take the same path: `urls`, `requests`, `method`, `headers`, `authorizationHeader` (reason `urls, requests, method, headers or authorizationHeader has the wrong type (<error>).`) and `timeoutSecs`, `retries`, `maxBodyChars`, `minDelayPerHostSecs`, `maxResults`, `maxConcurrency` (reason `<field> has the wrong type (<error>).`). The number check repeats the exact conversions the run makes; valid input behaves exactly as before.
- **Changed wording:** the terminal status message and log line for every invalid input (including the existing unsupported-method case) now read `Invalid input, nothing was fetched and no results were charged: <reason>` (was `Invalid input: <reason>`). The free status row itself is unchanged.
- Network, HTTP and upstream errors are unchanged.
- Memory: `defaultMemoryMbytes` is now 256 (was 1024); min 128 and max 4096 unchanged. The README does not name a memory size; the start fee is still 1 event at 256 MB.
- `requirements.txt`: `apify` pinned to `>= 4.1.0, < 4.2.0` (was `>= 4.0.0, < 5.0.0`).
- New unit tests: `tests/test_invalid_input.py`.

### Unreleased

- **Fixed (security): the private-address guard now rejects every address that is not globally routable** (`not ipaddress.is_global`), which adds carrier-grade NAT `100.64.0.0/10` (for example `100.64.0.1`, `100.127.255.254`) to the blocked ranges. The existing private, loopback, link-local, reserved, multicast and unspecified checks stay, and an IPv4-mapped IPv6 address (`::ffff:a.b.c.d`) is also checked as its IPv4 address. Applies on the Apify platform to each request URL and to every redirect hop. The reasons are unchanged: `private, loopback and link-local addresses are not allowed` and `DNS lookup failed for <host>`. Local runs still skip the check.
- Tests: blocked `100.64.0.1`, `100.127.255.254`, `192.0.0.1`, `198.18.0.1`, `0.0.0.0`, `::ffff:10.0.0.1`, `fc00::1`, `fe80::1` and allowed `93.184.216.34` (mocked DNS); DNS failure, off-platform skip and non-HTTP scheme.
