TOOLS

Fetch URL as Markdown API

Convert any web page into clean, LLM-ready Markdown. Fetches over plain HTTP with browser headers (retrying once through a residential or datacenter proxy when the origin serves a bot wall), removes boilerplate with Mozilla Readability, and converts with GitHub-flavored Markdown tables, lists and code blocks. Article mode is verified against a whole-page conversion and downgrades itself when Readability strips too much, so you are never handed a gutted page. Returns the markdown plus title, byline, language, excerpt, the extracted link list, the final URL after redirects, and which transport served the body. No browser is used, so a client-rendered page is reported as an error rather than as empty content.

Part of: URL to Markdown API

markdownhtmlreadabilityllmragscrapercontentconverter
Try it freeGet an API key

How to call it

Send one POST to api.upapi.io/fetch-markdown.post with your key in the X-Api-Key header and the parameters below as a JSON body. Each call spends 3 weighted units of your monthly quota. The operation times out after 25 seconds. Identical requests are served from cache for 300 seconds, unbilled.

endpoint
POST https://api.upapi.io/fetch-markdown.post

Fetch URL as Markdown API reference

Request parameters

url
stringrequired — Absolute http(s) URL of the page to convert (e.g. https://en.wikipedia.org/wiki/Markdown). Private, loopback and link-local destinations are refused.
mode
enum — article = Mozilla Readability main-content extraction, verified against the whole page and auto-downgraded when it strips too much; full = the whole body with nav/footer/aside/form removed (e.g. article).
maxChars
integer — Maximum characters of markdown to return (e.g. 100000). Output is cut at the nearest paragraph/line boundary and truncated is set.
timeoutMs
integer — Total network budget in milliseconds across the direct attempt and the one proxied retry (e.g. 20000). Capped below the 28s API-gateway edge timeout.
includeLinks
boolean — Keep inline [text](url) links in the markdown and return the extracted link list (e.g. true). false unwraps every anchor to plain text.
includeImages
boolean — Keep ![alt](url) image references in the markdown (e.g. false). Images are dropped by default because they cost tokens and rarely help an LLM.

Response fields

lang
objectrequired — Language tag from <html lang> (e.g. "en"); null if absent.
links
array — Absolute http(s) links found in the extracted content, capped at 500. Present only when includeLinks is true; reflects the extracted document, which may be longer than a truncated markdown body.
links[].href
stringrequired
links[].text
stringrequired
title
stringrequired — Page/article title, or an empty string if none was found.
byline
objectrequired — Author line, when Readability or a meta tag exposes one; null otherwise.
excerpt
objectrequired — Short summary from Readability or the meta description; null if absent.
finalUrl
stringrequired — URL actually fetched, after following redirects.
markdown
stringrequired — The converted document. Prefixed with the page title as an H1 when the extracted content does not already start with a heading.
charCount
integerrequired — Length of the returned markdown.
extractor
enumrequired — Which stage produced the markdown. In article mode this reads "full-dom" when Readability failed the content-density check.
fetchedAt
stringrequired — ISO-8601 timestamp of the fetch.
truncated
booleanrequired — True when the markdown was cut to fit maxChars.
httpStatus
integerrequired — HTTP status of the response that produced the markdown.
fetchedWith
enumrequired — Transport that produced the returned body: direct = straight from the worker; datacenter/residential = the proxy-pool tier used for the retry.

Example request and response

The example response is generated from this operation’s published output schema — it shows the shape and field names, not values from a recorded call.

json — example request body
{
  "url": "https://en.wikipedia.org/wiki/Markdown",
  "mode": "article",
  "maxChars": 100000,
  "timeoutMs": 20000,
  "includeLinks": true,
  "includeImages": false
}
json — example response shape
{
  "lang": "en",
  "links": [
    {
      "href": "example",
      "text": "Hello, world"
    }
  ],
  "title": "Alan Turing",
  "byline": {},
  "excerpt": {},
  "finalUrl": "example",
  "markdown": "example",
  "charCount": 1,
  "extractor": "readability",
  "fetchedAt": "example",
  "truncated": false,
  "httpStatus": 1,
  "fetchedWith": "direct"
}

Code snippets

cURL
curl
curl -X POST https://api.upapi.io/fetch-markdown.post \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: YOUR_API_KEY' \
  -d '{ "url": "https://en.wikipedia.org/wiki/Markdown", "mode": "article", "maxChars": 100000, "timeoutMs": 20000, "includeLinks": true, "includeImages": false }'
JavaScript
javascript
const response = await fetch('https://api.upapi.io/fetch-markdown.post', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_API_KEY',
  },
  body: JSON.stringify({
  "url": "https://en.wikipedia.org/wiki/Markdown",
  "mode": "article",
  "maxChars": 100000,
  "timeoutMs": 20000,
  "includeLinks": true,
  "includeImages": false
}),
});

const data = await response.json();
console.log(data);
Python
python
import requests

response = requests.post(
    'https://api.upapi.io/fetch-markdown.post',
    headers={
        'Content-Type': 'application/json',
        'x-api-key': 'YOUR_API_KEY',
    },
    json={
  "url": "https://en.wikipedia.org/wiki/Markdown",
  "mode": "article",
  "maxChars": 100000,
  "timeoutMs": 20000,
  "includeLinks": True,
  "includeImages": False
},
)

print(response.json())
Go
go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

func main() {
	payload := []byte(`{ "url": "https://en.wikipedia.org/wiki/Markdown", "mode": "article", "maxChars": 100000, "timeoutMs": 20000, "includeLinks": true, "includeImages": false }`)

	req, _ := http.NewRequest("POST", "https://api.upapi.io/fetch-markdown.post", bytes.NewBuffer(payload))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-api-key", "YOUR_API_KEY")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var result map[string]any
	json.Unmarshal(body, &result)
	fmt.Println(result)
}
PHP
php
<?php

$payload = json_encode([
    'url' => 'https://en.wikipedia.org/wiki/Markdown',
    'mode' => 'article',
    'maxChars' => 100000,
    'timeoutMs' => 20000,
    'includeLinks' => true,
    'includeImages' => false,
]);

$ch = curl_init('https://api.upapi.io/fetch-markdown.post');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $payload,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Content-Type: application/json',
        'x-api-key: YOUR_API_KEY',
    ],
]);

$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
var_dump($data);
Ruby
ruby
require 'net/http'
require 'uri'
require 'json'

uri = URI('https://api.upapi.io/fetch-markdown.post')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == 'https'

request = Net::HTTP::Post.new(uri.path)
request['Content-Type'] = 'application/json'
request['x-api-key'] = 'YOUR_API_KEY'
request.body = { "url": "https://en.wikipedia.org/wiki/Markdown", "mode": "article", "maxChars": 100000, "timeoutMs": 20000, "includeLinks": true, "includeImages": false }.to_json

response = http.request(request)
puts JSON.parse(response.body)
Java
java
import okhttp3.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;

OkHttpClient client = new OkHttpClient();
ObjectMapper mapper = new ObjectMapper();

String json = "{ \"url\": \"https://en.wikipedia.org/wiki/Markdown\", \"mode\": \"article\", \"maxChars\": 100000, \"timeoutMs\": 20000, \"includeLinks\": true, \"includeImages\": false }";

RequestBody body = RequestBody.create(json, MediaType.get("application/json"));
Request request = new Request.Builder()
    .url("https://api.upapi.io/fetch-markdown.post")
    .post(body)
    .addHeader("Content-Type", "application/json")
    .addHeader("x-api-key", "YOUR_API_KEY")
    .build();

try (Response response = client.newCall(request).execute()) {
    Map<?, ?> result = mapper.readValue(response.body().string(), Map.class);
    System.out.println(result);
}
C#
csharp
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");

var payload = JsonSerializer.Deserialize<object>("{ \"url\": \"https://en.wikipedia.org/wiki/Markdown\", \"mode\": \"article\", \"maxChars\": 100000, \"timeoutMs\": 20000, \"includeLinks\": true, \"includeImages\": false }");
var response = await client.PostAsJsonAsync("https://api.upapi.io/fetch-markdown.post", payload);

var result = await response.Content.ReadFromJsonAsync<JsonElement>();
Console.WriteLine(result);

Frequently asked questions

How much does the Fetch URL as Markdown API cost per call?

Each call spends 3 weighted units of your plan's monthly quota. Full pricing is at https://upapi.io/pricing.

How do I authenticate to the Fetch URL as Markdown API?

Send your key in the X-Api-Key header. A free guest key is available without creating an account.

Are Fetch URL as Markdown API responses cached?

Yes — identical requests are served from cache for 300 seconds, and a cache hit is not billed.

More Tools APIs

Browse every Tools API →