Extract text in Make, no dedicated module needed.

Make's module directory has no txtfetch entry. The generic HTTP app's Make a request module calls the same API, and a document link is a cleaner input than a binary bundle.

the-problem

A Make scenario that ingests documents usually pulls a file from a watched folder, an email module, or a form trigger. Forwarding that file as a binary bundle into a generic HTTP module works, but it adds a data-mapping step first. It also carries a real risk of getting the content type wrong. Make also caps how long a single module can run, so a scenario that waits on slow OCR can fail before the module returns anything.

how-to-wire-it-up

txtfetch has no dedicated Make module — no app to add, no OAuth connection to authorize. The HTTP app's Make a request module reaches the same REST endpoint a curl command would. Most Make triggers already expose a file's public or signed URL alongside its bundle. Pass that as the url query string parameter, instead of mapping the binary field. For a document that's large or slow, add async and webhook_url to the same request. Then let a second scenario start from a Webhooks module when the result lands.

  • Pass ?url= with the file's URL from the trigger bundle, so the HTTP module never maps a binary field.
  • Automatic OCR runs on scanned and photographed documents, in the same module call as any other format.
  • Async mode returns a job_id right away, so a slow extraction never exceeds the module's run limit.
  • A Webhooks module on a second scenario catches the webhook_url callback and continues from there.
  • Idempotency-Key support stops a re-run scenario from re-billing an extraction it already completed.

pass-a-link-not-a-file

curl
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/report.pdf" \
  -H "Authorization: Bearer $TXTFETCH_KEY"
Python
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/report.pdf"},
)

print(r.json()["extracted_text"])
JavaScript
const endpoint = new URL("https://api.txtfetch.com/v1/extract");
endpoint.searchParams.set("url", "https://example.com/report.pdf");

const res = await fetch(endpoint, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.TXTFETCH_KEY}` },
});

const { extracted_text } = await res.json();
console.log(extracted_text);
Go
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/report.pdf")
	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": "..."
}

large-or-slow-documents

POST /v1/extract returns 202 with a job_id whenever the document is large or slow to process, or whenever async=true is set. Poll GET /v1/extract/{job_id} for the result, or set webhook_url and have txtfetch push it instead. No single request on this page is safe to assume will always finish synchronously.

Submit (async)
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/report.pdf&async=true" \
  -H "Authorization: Bearer $TXTFETCH_KEY"

# {"status": "processing", "job_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"}
Poll
curl "https://api.txtfetch.com/v1/extract/3fa85f64-5717-4562-b3fc-2c963f66afa6" \
  -H "Authorization: Bearer $TXTFETCH_KEY"

# {"status": "processing", "job_id": "..."} while running, then the same
# {"status": "success", "extracted_text": "...", "metadata": {...}} shape
# POST /v1/extract would have returned synchronously.
curl
curl -X POST "https://api.txtfetch.com/v1/extract?url=https://example.com/report.pdf" \
  -H "Authorization: Bearer $TXTFETCH_KEY" \
  --data-urlencode "webhook_url=https://example.com/webhooks/txtfetch"

setup-steps

  1. Add an HTTP module and choose Make a request.
  2. Set Method to POST.
  3. Set URL to https://api.txtfetch.com/v1/extract, and add url as a query string parameter mapped to the document's link.
  4. Under Headers, add Authorization with the value Bearer, followed by your API key.
  5. For a large document, add async set to true and webhook_url set to a second scenario's Webhooks module address.
  6. Run the scenario once. The module's output bundle carries extracted_text for the next module to use.

faq

Does Make have a built-in txtfetch module?
No. There is no txtfetch app in the Make module library. The generic HTTP app's Make a request module calls the same REST API with no extra app to add.
How do I avoid mapping a binary field into the HTTP module?
Pass the file's URL from the trigger bundle as the url query string parameter instead. txtfetch fetches the document server-side, so the module never handles raw bytes.
What happens if a scenario's run limit is shorter than the OCR job?
Add async=true and webhook_url to the request. The module returns a job_id immediately, and a second scenario's Webhooks module picks up the finished result.
Can a Make scenario branch on a failed extraction?
Yes. Add a filter after the HTTP module that checks the status field. A failed request, marked by an error.code, routes down a different path than a success.

related-reading

Add the step to your Make flow.

One HTTP node with your key does the whole job.

Get an API key →

See every integration →