# URL to Markdown API — Fast Web Fetch for AI Agents (`fabrikit/url-to-markdown-api`) Actor

Fetch one URL and get clean Markdown back in about a second: title, description, main content without menus, cookie banners or ads, headings and word count. Batch mode (list of URLs → dataset) or Standby HTTP API for AI agents, RAG and MCP. From US$1.05 per 1,000 URLs.

- **URL**: https://apify.com/fabrikit/url-to-markdown-api.md
- **Developed by:** [Fabrikit](https://apify.com/fabrikit) (community)
- **Categories:** AI, Developer tools, Integrations
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 url converted to markdowns

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## URL to Markdown API — Fast Web Fetch for AI Agents

**URL to Markdown API fetches one web page and returns clean Markdown in about a second**, ready for an LLM prompt, a RAG pipeline or an MCP tool. Give it a URL and you get the main content without menus, footers, cookie banners or ads, plus the title, description, language, headings outline, word count, HTTP status and fetch time. It reads the HTML the server sends (no browser), so it is fast and cheap: **US$1.05 per 1,000 URLs**.

It does **not** crawl. One URL in, one Markdown document out. If you need a whole site or a docs section converted (sitemap, link depth, RAG chunks), use our [Website to Markdown Scraper](https://apify.com/fabrikit/website-to-markdown-scraper), which shares the same HTML-to-Markdown core.

### Two ways to call it

**1. Batch run** — paste a list of URLs, get one dataset record per URL. This is the normal Actor run (Console, API, schedules, integrations).

**2. Standby HTTP API** — the Actor keeps running and answers HTTP requests synchronously, like a hosted API:

```
GET https://fabrikit--url-to-markdown-api.apify.actor/?url=https://example.com/&format=markdown
Authorization: Bearer <your Apify token>
```

The exact Standby URL is shown on the Actor's **Standby** tab. Query parameters:

| Parameter | Default | Meaning |
|---|---|---|
| `url` | required | Page to fetch. `https://` is assumed when the scheme is missing. |
| `format` | `json` | `json` (full record), `markdown` (text/markdown body) or `text` (plain text body). |
| `removeBoilerplate` | `true` | Keep only the main content; `false` converts the whole page body. |
| `keepLinks` | `true` | Keep `[text](url)` links in the Markdown. |
| `keepImages` | `false` | Keep `![alt](src)` images. |
| `includeText` / `includeHtml` | `false` | Also return plain text / cleaned HTML in the JSON record. |
| `maxChars` | `0` | Cut the content at N characters (0 = no limit) to fit a context window. |
| `timeoutSecs` | `20` | Per-request timeout (3–60). |

`POST /` with the same fields as a JSON body works too. A request without `url` returns HTTP 400 with the usage; a page that could not be fetched returns 502 (or 422 when the server only sent an empty JavaScript shell) with the reason, so your agent never gets a blank document mistaken for content.

### What you get per URL

| Field | Description |
|---|---|
| `url`, `finalUrl` | Requested URL (normalised) and URL after redirects |
| `statusCode`, `contentType` | HTTP status and MIME type of the response |
| `title`, `description`, `language`, `canonicalUrl` | Page metadata |
| `markdown` | Main content as Markdown: headings, lists, tables, fenced code with language, links |
| `text`, `html` | Plain text / cleaned HTML, when requested |
| `textLength`, `wordCount`, `headings`, `linksCount` | Size and outline of the content |
| `needsBrowser` | `true` when the page is an empty JavaScript app shell (not charged) |
| `truncated` | `true` when `maxChars` or the 1.5M-character field cap cut the content |
| `fetchTimeMs`, `fetchedAt` | How long the fetch took and when |
| `error` | Why a URL failed (HTTP 404, timeout, blocked, unsupported type); `null` on success |

Plain text, Markdown, JSON and XML responses are passed through (JSON and XML inside a fenced block). PDFs and binaries are reported as unsupported rather than guessed.

### Input example (batch run)

```json
{
  "urls": [
    "https://example.com/",
    "https://en.wikipedia.org/wiki/Markdown",
    "https://docs.python.org/3/faq/general.html"
  ],
  "keepLinks": true,
  "maxChars": 20000
}
```

Duplicate URLs are skipped; invalid ones are listed in the log. `concurrency` (default 4) sets how many URLs are fetched in parallel.

### Output example

```json
{
  "url": "https://www.iana.org/help/example-domains",
  "finalUrl": "https://www.iana.org/help/example-domains",
  "statusCode": 200,
  "contentType": "text/html",
  "title": "Example Domains",
  "description": null,
  "language": null,
  "canonicalUrl": null,
  "markdown": "# Example Domains\n\nA number of domains such as `example.com` and `example.org` are maintained for documentation purposes...",
  "text": null,
  "html": null,
  "textLength": 756,
  "wordCount": 115,
  "headings": [{ "level": 1, "text": "Example Domains" }, { "level": 2, "text": "Further Reading" }],
  "linksCount": 31,
  "needsBrowser": false,
  "truncated": false,
  "fetchTimeMs": 225,
  "fetchedAt": "2026-10-20T05:17:58.979Z",
  "error": null
}
```

### Use cases

- **AI agents and MCP tools**: a "fetch this page" tool that returns Markdown instead of raw HTML, so the model spends tokens on content.
- **RAG and knowledge bases**: convert the pages your users cite, then embed `markdown` (set `maxChars` to keep documents bounded).
- **Summaries and extraction**: feed `markdown` to an LLM for summaries, Q\&A, entity or price extraction.
- **Link previews and content audits**: title, description, word count and outline for any list of URLs.
- **Reading services**: turn an article into clean text for e-mail digests or text-to-speech.

### Pricing

Pay per event. One event, `url-fetched`, is charged per URL converted to Markdown, in both modes.

| URLs converted | Cost |
|---|---|
| 100 | US$0.11 |
| 1,000 | US$1.05 |
| 10,000 | US$10.50 |

Not charged: failed fetches, HTTP 4xx/5xx answers, blocked requests, unsupported content types and pages flagged `needsBrowser`. Normal Apify compute and proxy usage apply on top of events only as described in your plan; the Actor runs with 512 MB and typically needs well under a second of compute per URL.

### How it compares

| | This Actor | [Website to Markdown Scraper](https://apify.com/fabrikit/website-to-markdown-scraper) (ours) | Official Web Fetch | Browser-based crawlers |
|---|---|---|---|---|
| Scope | Single URLs | Whole sites, docs sections | Single URLs | Sites or pages |
| Standby HTTP API | Yes | No | Yes | Varies |
| JavaScript rendering | No | No | No | Yes |
| Extras | `maxChars`, text/HTML, pass-through for JSON/XML | Sitemap, depth, globs, RAG chunks with overlap | — | Screenshots, JS apps |
| Price (Store, Oct 2026) | US$1.05 / 1,000 | US$0.50 / 1,000 pages | US$1.50 / 1,000 (Free tier) | Compute-based, usually more per page |

Pick the crawler when you need many pages from one site; pick a browser tool when the page is a JavaScript app (this Actor tells you with `needsBrowser: true`).

### Integrations

- **API**: run it with the [Apify API](https://docs.apify.com/api/v2) or client libraries (JavaScript, Python) and read the dataset, or call the Standby URL directly from any HTTP client.
- **AI agents / MCP**: expose it through the [Apify MCP server](https://apify.com/apify/actors-mcp-server) like any Actor, or give your agent the Standby URL as a plain HTTP tool (LangChain, LlamaIndex, CrewAI, OpenAI function calling, Claude tool use).
- **n8n, Make, Zapier**: use the Apify node/module to run the Actor with a list of URLs, or an HTTP node against the Standby URL.
- **Schedules and webhooks**: schedule batch runs and get notified when the dataset is ready.

### FAQ

**Is it legal?** Fetching a public page you could open in a browser is generally fine; respect the site's terms, copyright and rate limits, and do not use it for personal data. It only fetches the URLs you give it and never crawls.

**Do I need a proxy?** Requests go through Apify's datacenter proxy by default. If a site blocks that request, it is retried once through a residential proxy automatically; you can also set a residential proxy in `proxyConfiguration`. Sites behind aggressive anti-bot walls may still fail; they are reported in `error`, not charged.

**Why is `markdown` null?** Look at `error`: HTTP error, timeout, block, unsupported type, or `needsBrowser: true` (the server sent an empty JavaScript shell; use a browser-based tool for that page).

**Limits?** Responses over 8 MB are skipped; very large pages are converted up to a size budget and flagged `truncated`. Up to 10,000 URLs per batch run; use `maxChars` to bound each document.

**Does it run JavaScript?** No. That is what keeps it fast and cheap. Docs sites, blogs, news, wikis, product and marketing pages work well; single-page apps come back as `needsBrowser`.

### Changelog

- **0.1** (October 2026): first release. Batch mode and Standby HTTP API, JSON / Markdown / text formats, `maxChars`, pass-through for text, JSON and XML responses, datacenter-to-residential proxy fallback.

### En español

**URL to Markdown API** convierte una página web en Markdown limpio en alrededor de un segundo: entregas una URL y recibes el contenido principal sin menús, pies de página ni banners de cookies, más título, descripción, idioma, esquema de encabezados, conteo de palabras, estado HTTP y tiempo de descarga. Funciona en lote (lista de URLs → un registro por URL) o como API HTTP en modo Standby (`GET /?url=...&format=markdown`), pensada para agentes de IA, RAG y herramientas MCP. No usa navegador ni rastrea sitios: una URL, un Markdown. Si necesitas convertir un sitio completo, usa nuestro [Website to Markdown Scraper](https://apify.com/fabrikit/website-to-markdown-scraper). Precio: US$1,05 por cada 1.000 URLs convertidas; las descargas fallidas y las páginas que requieren navegador no se cobran.

# Actor input Schema

## `urls` (type: `array`):

Pages to convert, one URL each. No crawling: only these URLs are fetched. https:// is assumed when the scheme is missing; duplicates are skipped.

## `removeBoilerplate` (type: `boolean`):

Keep only the main content (drops navigation, footers, sidebars, cookie banners, ads). Turn off to convert the whole page body.

## `keepLinks` (type: `boolean`):

Keep hyperlinks as [text](url) in the Markdown. Turn off for link-free text.

## `keepImages` (type: `boolean`):

Keep images as ![alt](src) in the Markdown.

## `includeText` (type: `boolean`):

Also fill the text field with the plain text of the main content.

## `includeHtml` (type: `boolean`):

Also fill the html field with the cleaned HTML of the main content.

## `maxChars` (type: `integer`):

Cut markdown, text and html at this many characters (0 = no limit, up to 1,500,000). Handy to fit an LLM context window; truncated is set to true when the cut happens.

## `timeoutSecs` (type: `integer`):

Give up on a URL after this many seconds per attempt.

## `concurrency` (type: `integer`):

URLs fetched in parallel in a batch run.

## `proxyConfiguration` (type: `object`):

Apify datacenter proxy by default. When a site blocks the request, it is retried once through a residential proxy.

## Actor input object example

```json
{
  "urls": [
    "https://example.com/",
    "https://en.wikipedia.org/wiki/Markdown",
    "https://docs.python.org/3/faq/general.html",
    "https://www.iana.org/help/example-domains"
  ],
  "removeBoilerplate": true,
  "keepLinks": true,
  "keepImages": false,
  "includeText": false,
  "includeHtml": false,
  "maxChars": 0,
  "timeoutSecs": 20,
  "concurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `records` (type: `string`):

One item per URL

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://example.com/",
        "https://en.wikipedia.org/wiki/Markdown",
        "https://docs.python.org/3/faq/general.html",
        "https://www.iana.org/help/example-domains"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("fabrikit/url-to-markdown-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": [
        "https://example.com/",
        "https://en.wikipedia.org/wiki/Markdown",
        "https://docs.python.org/3/faq/general.html",
        "https://www.iana.org/help/example-domains",
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("fabrikit/url-to-markdown-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://example.com/",
    "https://en.wikipedia.org/wiki/Markdown",
    "https://docs.python.org/3/faq/general.html",
    "https://www.iana.org/help/example-domains"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call fabrikit/url-to-markdown-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fabrikit/url-to-markdown-api"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/2QRs7idt8fEpWybeU/builds/3IDpOw0euwMYWCBVL/openapi.json
