https://txtfetch.com/extract/zip/
One ZIP, every file's text back.
Skip the unzip-then-loop script. Point txtfetch at an archive and get every contained document's text back from one request.
the-problem
A folder of documents to ingest usually arrives zipped: an export from a CMS, a bulk upload, a batch of scanned forms. The typical pipeline is download, unzip, iterate the file list, call an extractor per file, and stitch the results back together. That's orchestration code, and it has nothing to do with the actual extraction problem.
one-request-solution
POST the .zip directly to txtfetch, and Apache Tika walks the archive. It extracts every contained file's text and folds it into one response. No unzip step, no per-file loop to write.
curl -X POST https://api.txtfetch.com/v1/extract \
-H "Authorization: Bearer $TXTFETCH_KEY" \
-F file=@batch-export.zipimport os
import requests
with open("batch-export.zip", "rb") as f:
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
files={"file": f},
)
print(r.json()["extracted_text"])import { readFile } from "node:fs/promises";
const file = new Blob([await readFile("batch-export.zip")]);
const form = new FormData();
form.append("file", file, "batch-export.zip");
const res = await fetch("https://api.txtfetch.com/v1/extract", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
body: form,
});
const { extracted_text } = await res.json();
console.log(extracted_text);package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
type extractResponse struct {
Status string `json:"status"`
ExtractedText string `json:"extracted_text"`
}
func main() {
f, err := os.Open("batch-export.zip")
if err != nil {
panic(err)
}
defer f.Close()
var body bytes.Buffer
writer := multipart.NewWriter(&body)
part, err := writer.CreateFormFile("file", "batch-export.zip")
if err != nil {
panic(err)
}
if _, err := io.Copy(part, f); err != nil {
panic(err)
}
writer.Close()
req, err := http.NewRequest("POST", "https://api.txtfetch.com/v1/extract", &body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY"))
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result extractResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
panic(err)
}
fmt.Println(result.ExtractedText)
}Or skip the download. Pass a url parameter and txtfetch fetches the document server-side:
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/exports/batch-2024-06.zip" \
-H "Authorization: Bearer $TXTFETCH_KEY"import os
import requests
r = requests.post(
"https://api.txtfetch.com/v1/extract",
headers={"Authorization": f"Bearer {os.environ['TXTFETCH_KEY']}"},
params={"url": "https://example.com/exports/batch-2024-06.zip"},
)
print(r.json()["extracted_text"])const endpoint = new URL("https://api.txtfetch.com/v1/extract");
endpoint.searchParams.set("url", "https://example.com/exports/batch-2024-06.zip");
const res = await fetch(endpoint, {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
});
const { extracted_text } = await res.json();
console.log(extracted_text);package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
)
type extractResponse struct {
Status string `json:"status"`
ExtractedText string `json:"extracted_text"`
}
func main() {
endpoint, err := url.Parse("https://api.txtfetch.com/v1/extract")
if err != nil {
panic(err)
}
q := endpoint.Query()
q.Set("url", "https://example.com/exports/batch-2024-06.zip")
endpoint.RawQuery = q.Encode()
req, err := http.NewRequest("POST", endpoint.String(), nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("TXTFETCH_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var result extractResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
panic(err)
}
fmt.Println(result.ExtractedText)
}{
"status": "success",
"extracted_text": "..."
}what-comes-back
The corpus behind /diff has no recorded .zip document yet, so we have nothing honest to show you here. Run one of your own instead. The free converter reads the file in your browser, and nothing is uploaded.
formats-covered
.zip
faq
- Can I extract text from every file in a ZIP archive at once?
- Yes. POST the .zip to https://api.txtfetch.com/v1/extract, and txtfetch walks the archive. It returns the extracted text of every contained file in one { "status": "success", "extracted_text": "..." } response.
- What file types can be inside the ZIP?
- Any format txtfetch supports: PDFs, Office documents, HTML, images, email, mixed within a single archive.
- Do nested folders inside the ZIP matter?
- No. Tika walks the archive structure recursively, so nested directories inside the ZIP are handled the same as top-level files.
go-further
Books & archives
Send a real .zip through it.
One HTTP call returns the text. Read one in your browser first, for free.
Get an API key →