SFOLN

Catalogue / Web toolkit for agents

URL to Markdown & Article Extractor

sfoln/url-to-markdown-summary · AI, Agents, Developer tools On request

Turn web pages into clean markdown with the main article only: title, author, publish date, site name, word and token counts. Optional AI summary with key points, keywords and entities. Built for RAG, agents and content pipelines. $1.50 per 1,000 pages; summaries $4 per 1,000.

About

What it does

Turn web pages into clean markdown of their main article, ready for LLMs, RAG pipelines and AI agents. For every URL you get the article as GitHub-flavoured markdown (headline, headings, paragraphs, lists, links and tables; menus, ads, share buttons, cookie banners and footers removed), its metadata (title, author, publish date, site name, canonical URL, Open Graph image), word and token counts and, optionally, a structured AI summary: a short abstract, 3–7 key points, keywords, named entities, the language and the content type. $1.50 per 1,000 pages, summaries $4 per 1,000; broken, missing or non-HTML pages are free.

Price

Price per delivered record

EventPricePer 1,000Charged for
Markdown page
url-markdown
$0.0015$1.5 / 1,000Charged once per URL whose page was fetched and its main content converted to readable markdown with metadata.
Page summary
url-summary
paid plans only
$0.004$4 / 1,000Charged once per URL for which the AI summary (summary, key points, keywords, entities, language, content type) was generated.

Apify free plan: up to 10 items per run. Paid plans have no per-run cap; set maxTotalChargeUsd to cap spend.

Run

Call it from code, an agent or the Console

This API is private on Apify for now. Email us and we will publish it for you, usually within two working days. The calls below work once it is public. contact@sfoln.com

curl · synchronous run, rows in the response
curl -X POST "https://api.apify.com/v2/actors/sfoln~url-to-markdown-summary/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls":["https://en.wikipedia.org/wiki/Web_scraping"]}'
mcp.json · hosted Apify MCP server
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=sfoln/url-to-markdown-summary"
    }
  }
}
asynchronous run · for large batches
POST https://api.apify.com/v2/actors/sfoln~url-to-markdown-summary/runs?maxTotalChargeUsd=1
GET  https://api.apify.com/v2/actor-runs/{runId}            # until status is SUCCEEDED
GET  https://api.apify.com/v2/datasets/{defaultDatasetId}/items?format=json

Authenticate with an Apify API token. MCP clients can instead sign in with OAuth when prompted. Example prompt for an agent: Convert https://en.wikipedia.org/wiki/Web_scraping to markdown and give me its key points.

Input

Input fields

List web page URLs. Each URL produces one dataset record with markdown, metadata and (optionally) a structured summary.

FieldTypeDefaultMeaning
urls *arrayrequiredURLs
Web page URLs (http/https), one per line. Accounts on the Apify free plan can process up to 10 URLs per run.
summarizebooleantrueSummarize with AI
Add a structured summary (summary, key points, keywords, entities, language, content type) generated by Mistral AI. Charged per summarized URL (url-summary).
summaryLanguagestring—Summary language
Language for the summary and key points, e.g. "English" or "de". Empty = the page's own language.
maxWordsinteger120Max summary words
Upper limit for the summary length in words (20–300). Range 20–300.
includeMarkdownbooleantrueInclude markdown
Include the page's readable content as markdown (up to 200,000 characters). Turn off if you only need the summary.
extractorstring"article"Extractor
article: the page's main article (Mozilla Readability with a safety net, the default). full: every section of the page's main region, as before v2 (documentation and landing pages). One of "article", "full".
maxUrlsinteger1000Max URLs
Safety cap on how many URLs are processed in this run; URLs beyond it are reported as dropped. Range 1–10000.
concurrencyinteger3Concurrency
URLs processed in parallel (1–10). Range 1–10.
Example input
{
  "urls": [
    "https://en.wikipedia.org/wiki/Web_scraping"
  ]
}

Output

One record per input item

Records land in the run's dataset; a synchronous call returns them directly. Each has a status (ok is charged; everything else is free) and a charged flag. The run's OUTPUT record totals items and charges.

FieldTypeMeaning
inputstring | objectInput
The input item this record corresponds to.
statusstringStatus
ok | not_found | error | skipped_invalid | skipped_budget | skipped_free_plan
chargedbooleanCharged
Whether the record's main event was charged.
chargedEventstring | nullCharged event
Event charged by the runner for this record, if any.
sourcestringSource
Upstream data source.
fetchedAtstringFetched at
ISO timestamp.
warningsarray | nullWarnings
Non-fatal problems (pages not reachable, truncation, budget limits).
errorobject | nullError
{ code, message, provider?, status? } when status is not ok.
urlstring | nullURL
Normalized input URL.
finalUrlstring | nullFinal URL
URL after redirects.
titlestring | nullTitle
Page <title> (or og:title).
descriptionstring | nullDescription
Meta description / og:description.
canonicalstring | nullCanonical URL
rel=canonical or og:url.
authorstring | nullAuthor
Author line (Readability byline, meta author or JSON-LD article author).
publishedAtstring | nullPublished at
ISO 8601 (UTC) publication time from the page (article:published_time, JSON-LD datePublished or Readability), when it states a valid one.
siteNamestring | nullSite name
og:site_name or the publisher name.
ogImagestring | nullOpen Graph image
og:image URL.
markdownstring | nullMarkdown
The page's main content as GitHub-flavoured markdown (headline, headings, paragraphs, lists, links, tables), max 200,000 characters.
markdownTruncatedboolean | nullMarkdown truncated
true when the markdown was cut at 200,000 characters.
wordCountinteger | nullWord count
Words in the extracted markdown.
tokenEstimateinteger | nullToken estimate
Rough LLM token count of the markdown (about 4 characters per token).
extractorstring | nullExtractor
readability (Mozilla Readability's article) | fallback (full main region: used when Readability would drop part of the page, for very large pages, and with extractor full) | text (a plain-text page).
summarystring | nullSummary
AI summary (≤ maxWords words).
keyPointsarray | nullKey points
3–7 key points.
keywordsarray | nullKeywords
Up to 10 keywords.
entitiesobject | nullEntities
{ people[], organizations[], places[] } mentioned on the page.
languagestring | nullLanguage
ISO 639-1 code of the page language (from the summary, else the html lang attribute).
contentTypestring | nullContent type
article | product | docs | other (null without summary).
summaryChargedboolean | nullSummary charged
true when url-summary was charged for this URL.
summaryInputTruncatedboolean | nullSummary input truncated
true when only the first ≈4,000 tokens of the page were summarized.
tokensUsedobject | nullTokens used
{ input, output } Mistral tokens for the summary.
Example record
{
  "input": "https://acme.com/blog/widgets",
  "url": "https://acme.com/blog/widgets",
  "finalUrl": "https://acme.com/blog/widgets",
  "title": "Widgets explained | Acme Blog",
  "description": "All about widgets.",
  "canonical": "https://acme.com/blog/widgets",
  "author": "Jane Example",
  "publishedAt": "2026-09-30T08:00:00.000Z",
  "siteName": "Acme Blog",
  "ogImage": "https://acme.com/img/widgets.png",
  "markdown": "# Widgets explained\n\nWidgets are small mechanical parts ...\n\n- Cheap\n- Durable",
  "markdownTruncated": false,
  "wordCount": 1240,
  "tokenEstimate": 1910,
  "extractor": "readability",
  "summary": "Widgets are small mechanical parts made by Acme Corp in Berlin ...",
  "keyPoints": [
    "Widgets are cheap",
    "They are durable",
    "Acme makes them in Berlin"
  ],
  "keywords": [
    "widgets",
    "Acme",
    "manufacturing"
  ],
  "entities": {
    "people": [
      "Jane Example"
    ],
    "organizations": [
      "Acme Corp"
    ],
    "places": [
      "Berlin"
    ]
  },
  "language": "en",
  "contentType": "article",
  "summaryCharged": true,
  "summaryInputTruncated": false,
  "tokensUsed": {
    "input": 1812,
    "output": 196
  },
  "status": "ok",
  "charged": true,
  "chargedEvent": "url-markdown",
  "source": "website+mistral",
  "fetchedAt": "2026-10-14T10:00:00.000Z"
}

FAQ

Questions

How is the main content found?
Each page is parsed with Mozilla Readability (the engine of Firefox Reader View) on a full DOM with links made absolute. Its result is used only when it keeps the opening paragraphs and at least 85% of the text of the page's main region; otherwise a second extractor that keeps every section is used (documentation pages, for example; also for very large pages, over 800 KB of HTML, 10,000 elements or 128 levels of nesting, and when extractor is full). Navigation, share buttons, tag clouds and other page chrome are removed, tables become GitHub-flavoured markdown tables, and the markdown starts with the article's headline.
Which pages do not work?
Pages that build their content with JavaScript, sit behind a login or a bot check return little or no text: such URLs end as no_text or thin_content errors and are not charged. PDFs and other files are not converted (not_html).

Machine-readable

This page for agents