# Changelog of PDF Text Extractor: PDF URL to text for AI and RAG (`fecklesspleb/pdf-text-extractor`) Actor

- **URL**: https://apify.com/fecklesspleb/pdf-text-extractor/changelog.md
- **Full Actor documentation**: https://apify.com/fecklesspleb/pdf-text-extractor.md

## Changelog

### 2026-11-02 (actor.json version unchanged: 1.0): private-address (SSRF) guard

- On the Apify platform, every request (the PDF URL, each redirect hop, and robots.txt) is refused when the host
  resolves to a private, loopback, link-local, carrier-grade NAT, reserved, multicast or unspecified address
  (including IPv4-mapped IPv6), or when any of the host's addresses is one. Same rules as Bulk HTTP Request.
- Such a URL is never charged (other error rows are still charged as before, see Pricing). With `includeFailedUrls`
  on it gets a free row: `error: "not fetched: private, loopback and link-local addresses are not allowed"`,
  `status: "error"`, `message: "Not charged: this URL was not fetched (...)"`. With `includeFailedUrls` off it is
  dropped; if no row is output at all, the dataset gets one free status row (`recordType: "status"`,
  `message: "Not charged: N URL(s) were not fetched (...)"`). It counts as `failed` in `RUN_SUMMARY`.
- A host the guard cannot resolve fails as a DNS error, as before (still a charged error row, as before); only the
  text now reads "DNS or connection error: DNS lookup failed for <host>".
- A robots.txt that redirects to a private address counts as unavailable (no robots.txt rules).
- Local runs (APIFY_IS_AT_HOME not set) are unchanged.
- Files: `my_actor/common.py` (guard helpers, `blocked_status_row`; `Http._robots_for` checks the site first),
  `my_actor/main.py` (hook on the httpx client, `Blocked` handled), `tests/test_ssrf_guard_1102t.py` (new),
  README Limits (one line), this CHANGELOG (new).
