Web and domain tooling

Web Page to Markdown for LLMs: clean text from any URL

The main content of web pages as Markdown and plain text, up to 500 URLs per run: title, description, author, date, language, word count, links and images, without menus, cookie banners and footers, ready for LLMs, search indexes and archives. Pay per page.

$1.00per 1,000 · Page converted

One page delivered as Markdown and text. Pages that cannot be fetched or hold no readable content are never charged.

Call it from your code

curl
ACTOR=steadydata~webpage-to-markdown
URL="https://api.apify.com/v2/acts/$ACTOR/run-sync-get-dataset-items"

curl -X POST "$URL?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://en.wikipedia.org/wiki/Web_scraping"], "includeLinks": true, "includeTables": true}'
python
import os, requests

ACTOR = "steadydata~webpage-to-markdown"
URL = f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items"

rows = requests.post(
    URL,
    params={"token": os.environ["APIFY_TOKEN"]},
    json={'urls': ['https://en.wikipedia.org/wiki/Web_scraping'], 'includeLinks': True, 'includeTables': True},
    timeout=900,
).json()

# every row carries a status; failures are records, not exceptions
ok = [r for r in rows if r.get("status") == "ok"]
print(len(ok), "rows delivered")
javascript
const ACTOR = "steadydata~webpage-to-markdown";
const url =
  `https://api.apify.com/v2/acts/${ACTOR}/run-sync-get-dataset-items` +
  `?token=${process.env.APIFY_TOKEN}`;

const rows = await fetch(url, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"urls": ["https://en.wikipedia.org/wiki/Web_scraping"], "includeLinks": true, "includeTables": true}),
}).then((r) => r.json());

// one object per delivered row, same shape every time
console.log(rows.filter((r) => r.status === "ok").length, "rows");

Use it in an agent

Point an MCP client at Apify's hosted server with this dataset in the tools list, or run our own server locally.

mcp url
https://mcp.apify.com?tools=steadydata/webpage-to-markdown

# the tool arrives in your agent as steadydata--webpage-to-markdown

Input

FieldTypeNameWhat it does
urls
required
array of stringPage URLsOne URL per row, up to 500.
includeLinksbooleanKeep links in the MarkdownOn: links stay as [text](url) in the Markdown. Off: link text only.
includeTablesbooleanKeep tablesTables become Markdown tables.
fullPagebooleanWhole page instead of main contentOff: only the main content (article, product text) is extracted. On: everything readable on the page, menus and footers included.

What you get back

output schema, one object per delivered row
{
  "url": string | null,
  "finalUrl": string | null,
  "title": string | null,
  "description": string | null,
  "author": string | null,
  "publishedDate": string | null,
  "language": string | null,
  "siteName": string | null,
  "markdown": string | null,
  "text": string | null,
  "wordCount": integer | null,
  "linkCount": integer | null,
  "imageCount": integer | null,
  "canonicalUrl": string | null,
  "fetchedAt": string | null,
  "status": string | null,
  "input": string | null,
  "errorCode": string | null,
  "error": string | null
}
FieldTypeWhen it is filled
urlstring, null
finalUrlstring, null
titlestring, null
descriptionstring, null
authorstring, null
publishedDatestring, null
languagestring, null
siteNamestring, null
markdownstring, null
textstring, null
wordCountinteger, null
linkCountinteger, null
imageCountinteger, null
canonicalUrlstring, null
fetchedAtstring, null
statusstring, nullEither 'ok' or 'error'. An error row carries errorCode and error, and leaves the data fields empty; it is never charged.
inputstring, nullThe input this row was built from, so a row can always be traced back.
errorCodestring, nullFilled on an error row only; a delivered row leaves it empty.
errorstring, nullFilled on an error row only; a delivered row leaves it empty.

Related datasets

Already using this one? Ratings are the first thing other buyers look at, and this dataset has none yet. If it does a job for you, a rating on its Apify page is the one thing that helps. It takes a minute and it is the only thing we ask for.

Open the Apify page