https://txtfetch.com/docs/where-your-file-goes/
Where your file goes
/docs/personal-data traces your text after it leaves txtfetch. This page traces the minutes before that, inside txtfetch itself.
One document, hop by hop
Every row below names the file that enforces it. Read the source before you trust the claim.
| Hop | Held by | Region | How long |
|---|---|---|---|
| Edge | CloudFront and API Gateway | Nearest AWS edge location | Not held. Passed straight through. |
| The extract Lambda | The extract Lambda function | us-west-2 (Oregon) | One request. Freed when it ends. |
| A ?url= fetch | The extract Lambda, on your behalf | us-west-2 (Oregon) | The length of the fetch. Not stored. |
| The S3 buffer | A private S3 bucket | us-west-2 (Oregon) | 1 day, then the object is gone. |
| The async result | The same S3 bucket | us-west-2 (Oregon) | 1 day, the same rule as the buffer. |
| An idempotency record | The same S3 bucket | us-west-2 (Oregon) | 1 day, the same rule as the buffer. |
| A webhook | Your own server | Wherever you host webhook_url | Set by you. This hop is yours. |
| Logs | CloudWatch Logs | us-west-2 (Oregon) | 14 days, then the log group expires it. |
| Usage records | DynamoDB | us-west-2 (Oregon) | Metadata only, on its own retention schedule. |
| The premium tier | Nobody. This hop does not run. | None. Not in production. | Never reached. |
- Edge
- CloudFront and API Gateway end the TLS connection at the edge. They read request metadata to route the call, and pass your document bytes straight through.
terraform/api-extract/edge.tf, apigateway.tf - The extract Lambda
- Your document bytes sit in the function's memory for the length of one request. Tika and Tesseract run in that same process. Nothing is written to disk on this hop.
terraform/api-extract/state.tf:26-27 (the default provider's region), config.js:69: AWS_REGION default - A ?url= fetch
- Pass ?url= instead of a file, and txtfetch fetches it for you. The target site sees an AWS address, not your own. A port allowlist, a redirect cap, and an SSRF check all run again on every redirect hop, not just the first one.
api/extract/src/fetch-url.js:33, ssrf.js - The S3 buffer
- A large or slow input buffers to S3 under buffer/<job_id>/input, encrypted at rest with AES256. Bucket versioning is switched off on purpose: a kept prior version of your document is exactly the retention this API promises not to have.
terraform/api-extract/jobs.tf:22-27 (encryption), jobs.tf:31-38 (versioning), jobs.tf:46-60 (1-day expiry) - The async result
- For an async job, result.json holds your extracted text in the same bucket, under the same one-day rule. This is the one hop where extracted text rests on disk rather than in memory.
api/extract/src/jobs.js:114-142 (resultKey, putResult, getJobStatus) - An idempotency record
- Replay a request with the same Idempotency-Key, and txtfetch stores the response it sent back, under the same prefix and the same one-day rule.
api/extract/src/jobs.js:144-166 (idemRecordKey, putIdemRecord, getIdemRecord) - A webhook
- Give txtfetch a webhook_url, and it POSTs the finished result there, signed with HMAC so you can verify it came from txtfetch. Past this point, retention is your call, not ours.
api/extract/src/webhook.js (HMAC signature), config.js: WEBHOOK_SIGNING_SECRET - Logs
- A request log carries an allowlist of body-free fields: request ID, method, route, mode, content type, size, whether it was async, and a key ID. Your document body and the extracted text never reach the logger. The module has no dependencies, so a CI check can prove that directly.
api/extract/src/redact.js:6-27, terraform/api-extract/lambda.tf:27 and apigateway.tf:79 (14-day retention) - Usage records
- A usage counter and a usage record track that a request happened, its size, and its status. Neither holds your document or its extracted text. See the full retention schedule on the limits page.
api/extract/src/config.js: COUNTER_RETENTION_DAYS, USAGE_RECORD_RETENTION_DAYS - The premium tier
- ?quality=premium is sold as a tier, but VLM_ENABLED defaults to false and no operator has switched the tier on in production. Every premium request downgrades to the standard Tika path instead. This would be the only hop that sends content outside the txtfetch AWS account.
api/extract/src/config.js:132: VLM_ENABLED, vlm.js:21 (ANTHROPIC_BASE_URL), terraform/api-extract/variables.tf:229-233
The one hop that would leave the building
?quality=premium is sold as a tier, but it does not run today. VLM_ENABLED defaults to false, and no operator has switched the tier on in production. A premium request downgrades to the standard Tika path instead.
The tier is listed on /pricing. See /docs/limits for its page and byte caps, and /compare/multimodal-llm for what it is for.
What this page does not cover
This page stops at txtfetch's own door. What happens to your extracted text after that, your log, your prompt, your embedding provider, your vector store, is covered on /docs/personal-data. Usage-record retention has its own full schedule on /docs/limits.
Watch it run, then take a key.
The playground replays a real recorded response for every sample document.
Open the playground →