Skip to main content
FileRouter accepts your document in whatever form it naturally exists in your code — a URL you fetched, a file path on disk, a browser File object, raw bytes, or a streaming body from a network response. Before passing anything to a provider, FileRouter resolves the input once into a canonical, provider-safe form. This resolution step is what lets compare() run multiple providers concurrently without consuming a one-shot stream more than once.

Accepted input types

You can pass any of the following as the first argument to parse() or compare():

HTTP URL

A string starting with http:// or https://, or a URL object. FileRouter validates the URL and passes it directly to the provider — the document is never downloaded into your runtime.

Local file path

A plain string file path (e.g. "/tmp/report.pdf") or the explicit object { kind: "file", path: "/tmp/report.pdf" }. FileRouter reads the file from disk into bytes.

File or Blob

A browser or Node.js File or Blob instance. FileRouter preserves the filename and MIME type from the object when available.

ArrayBuffer or typed array

An ArrayBuffer or any ArrayBufferView (such as Uint8Array). Useful when you have already read bytes into memory.

ReadableStream

A web ReadableStream<Uint8Array>. FileRouter consumes the stream once and converts it to replayable bytes before dispatch.

Explicit bytes object

The structured form { kind: "bytes", data, mimeType?, name? } lets you supply bytes alongside explicit metadata when you already know the filename and MIME type.
The full ParseInput type from the SDK captures all of these forms:
parse-input-type.ts

How inputs are resolved

FileRouter resolves every input exactly once into one of two canonical, provider-safe representations before any provider call is made:
  • A validated HTTP URL — used when your input is already an http:// or https:// URL. FileRouter validates the URL format and passes it directly to the provider. The file is never downloaded into your runtime.
  • Replayable bytes — used for everything else. The input (file, buffer, stream, or path) is read into an in-memory Blob with a normalized filename and resolved MIME type.
The one-time resolution is critical for compare(). A ReadableStream can only be consumed once. FileRouter reads it into replayable bytes first, then fans the same bytes out to each provider concurrently — your stream is never partially consumed.

MIME type resolution

FileRouter resolves the MIME type of your document deterministically using the following priority order:
1

Explicit non-generic MIME type

If you supply a mimeType directly (via a File, Blob, or the { kind: "bytes" } form) and it is a specific, non-generic type (not application/octet-stream), FileRouter uses it as-is.
2

Filename extension

If the explicit MIME type is absent or generic, FileRouter infers the type from the filename extension — for example, .pdfapplication/pdf, .docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document.
3

Fallback to octet-stream

If neither step produces a specific type, FileRouter falls back to application/octet-stream and lets the provider decide how to handle the bytes.
MIME metadata is purely informational. It is attached to the resolved input and forwarded to the provider as a hint, but it does not select a provider, change the requested operation, or cause FileRouter itself to reject the document.

Unknown file signatures

FileRouter does not reject a document simply because its binary signature is unrecognized. Text-based formats like CSV and Markdown have no reliable binary signature, and provider support for new formats evolves independently of FileRouter releases. If you send a .csv file, FileRouter resolves the MIME type from the extension and forwards it to your chosen provider.
You can check how FileRouter resolves the MIME type of any document locally — without sending it anywhere — using inspectDocument() from @file_router/sdk/inspect. This function reports the resolved type, the extension-derived type, the detected binary signature type, and whether they conflict.

Hosted uploads

When you use the hosted API (FileRouterClient), your document streams directly from the request body into private cloud storage. FileRouter never buffers the full file in memory during ingress.

Upload limit

The hosted endpoint accepts files up to 100 MB.

Streaming ingress

Your file streams directly to storage — it is never parsed as multipart or accumulated in memory by FileRouter during upload.
Files larger than 100 MB are not supported by the hosted upload endpoint. A future direct-upload session will lift this limit without changing the parsing contract. If you are testing locally with the hosted API, note that localhost URLs cannot be fetched by external providers — use a public development tunnel when testing hosted parses against local files.