Turn Any Webpage or Document into Clean AI-Ready Markdown

Extract text and main content from web url or file with ease while reliably filtering noise such as headers, footers, menu, sidebars etc. Supports a wide range of file formats including pdf, word, powerpoint, excel, images, epub, zip and many more.

Simple Markdown API
> Simply prepend https://platform.lemino.ai/api/url2md/ before any url!
> To try in your browser click here or copy paste below command into terminal:
curl "https://platform.lemino.ai/api/url2md/https://www.example.com"

Simple Yet Powerful

Flexible extraction of markdown text from urls, documents and images

URL Conversion

Extracts clean content from urls into perfectly formatted markdown. Handles JavaScript and dynamic modern websites.

Document Processing

Converts pdf, docx, pptx, xlsx, jpg, png, epub, html, json, zip and many more file formats to markdown.

Intelligent Filtering

Intelligently extracts main content while reliably filtering noise such as headers, footers, menu, sidebars, ads etc.

Converters

Purpose-built converters for every file type

URL to Markdown PDF to Markdown PowerPoint to Markdown Word to Markdown Excel to Markdown HTML to Markdown CSV to Markdown YouTube to Markdown Image to Markdown JSON to TOON

API Playground

Test your own urls and documents to markdown conversion right here

Request Configuration

Leave empty to use demo mode with limited quota

Response

No response yet

Send a request to see the converted Markdown

You Don't Need Docs!

Who reads documentation when it's so easy to do?

cURL Example
URL="https://www.example.com"

curl -X GET https://platform.lemino.ai/api/url2md/$URL \
  -H "x-api-key: YOUR_API_KEY" \
  -H "accept: text/plain"
JavaScript (Fetch)
const url = 'https://www.example.com';
const apiUrl = 'https://platform.lemino.ai/api/url2md/' + url;

const response = await fetch(apiUrl, {
  method: 'GET',
  headers: {
    'x-api-key': 'YOUR_API_KEY',
    'accept': 'text/plain'
  }
});

const markdown = await response.text();
console.log(markdown);
Python (requests)
import requests

url = 'https://www.example.com'
api_url = 'https://platform.lemino.ai/api/url2md/' + url

headers = {
    'x-api-key': 'YOUR_API_KEY',
    'accept': 'text/plain'
}

response = requests.get(api_url, headers=headers)
markdown = response.text

print(markdown)
PHP (cURL)
<?php

$url = 'https://www.example.com';
$api_url = 'https://platform.lemino.ai/api/url2md/' . $url;

$headers = [
    'x-api-key: YOUR_API_KEY',
    'accept: text/plain'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

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

echo $response;

?>
Go (net/http)
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    url := "https://www.example.com"
    apiUrl := "https://platform.lemino.ai/api/url2md/" + url
    
    req, _ := http.NewRequest("GET", apiUrl, nil)
    req.Header.Add("x-api-key", "YOUR_API_KEY")
    req.Header.Add("accept", "text/plain")
    
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}
Ruby (net/http)
require 'net/http'
require 'uri'

url = 'https://www.example.com'
api_url = 'https://platform.lemino.ai/api/url2md/' + url

uri = URI(api_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
request['x-api-key'] = 'YOUR_API_KEY'
request['accept'] = 'text/plain'

response = http.request(request)
puts response.body
Java (HttpClient)
import java.net.http.*;
import java.net.URI;

public class ApiClient {
    public static void main(String[] args) throws Exception {
        String url = "https://www.example.com";
        String apiUrl = "https://platform.lemino.ai/api/url2md/" + url;
        
        HttpClient client = HttpClient.newHttpClient();
        
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(apiUrl))
                .header("x-api-key", "YOUR_API_KEY")
                .header("accept", "text/plain")
                .build();
        
        HttpResponse<String> response = client.send(request, 
                HttpResponse.BodyHandlers.ofString());
        
        System.out.println(response.body());
    }
}
Kotlin (OkHttp)
import okhttp3.*
import java.io.IOException

fun main() {
    val url = "https://example.com"
    val apiUrl = "https://platform.lemino.ai/api/url2md/" + url
    
    val client = OkHttpClient.Builder()
        .connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
        .readTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
        .writeTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
        .build()
    
    val request = Request.Builder()
        .url(apiUrl)
        .addHeader("x-api-key", "YOUR_API_KEY")
        .addHeader("accept", "text/plain")
        .build()
    
    val response = client.newCall(request).execute()
    println(response.body?.string())
}
Swift (URLSession)
import Foundation

let url = "https://example.com"
let apiUrl = "https://platform.lemino.ai/api/url2md/" + url

guard let requestUrl = URL(string: apiUrl) else {
    print("Invalid URL")
    exit(1)
}

var request = URLRequest(url: requestUrl)
request.httpMethod = "GET"
request.setValue("YOUR_API_KEY", forHTTPHeaderField: "x-api-key")
request.setValue("text/plain", forHTTPHeaderField: "accept")

let semaphore = DispatchSemaphore(value: 0)

let task = URLSession.shared.dataTask(with: request) { data, response, error in
    if let error = error {
        print("Error: \(error)")
    } else if let data = data, let result = String(data: data, encoding: .utf8) {
        print(result)
    }
    semaphore.signal()
}

task.resume()
semaphore.wait()
C++ (libcurl)
#include <iostream>
#include <string>
#include <curl/curl.h>

size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* response) {
    size_t totalSize = size * nmemb;
    response->append((char*)contents, totalSize);
    return totalSize;
}

int main() {
    std::string url = "https://example.com";
    std::string apiUrl = "https://platform.lemino.ai/api/url2md/" + url;
    
    CURL* curl;
    CURLcode res;
    std::string response;
    
    curl = curl_easy_init();
    if(curl) {
        struct curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "x-api-key: YOUR_API_KEY");
        headers = curl_slist_append(headers, "accept: text/plain");
        
        curl_easy_setopt(curl, CURLOPT_URL, apiUrl.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        
        res = curl_easy_perform(curl);
        
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    
    std::cout << response << std::endl;
    return 0;
}
C# (HttpClient)
using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string url = "https://example.com";
        string apiUrl = "https://platform.lemino.ai/api/url2md/" + url;
        
        using var client = new HttpClient();
        
        client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
        client.DefaultRequestHeaders.Add("accept", "text/plain");
        
        try
        {
            var response = await client.GetAsync(apiUrl);
            
            string result = await response.Content.ReadAsStringAsync();
            Console.WriteLine(result);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }
}

💡 Prefer JSON over plain text? If you're a seasoned developer who loves JSON, just use the accept header accept: application/json instead. As a by-product you get a list of text chunks in well-formed JSON. Chunking large documents is a common practice when working with AI models. You can select the relevant chunks only to feed to your LLM to reduce context size and token cost.

Simple, Transparent Pricing

Pay only for what you use. No monthly fees, no commitments.

Pay Per Use

$1

For every 1,000 page conversions

URLs and many file formats supported
High-quality Markdown output
Priority support
No rate limits

Start with 5000 free page conversions • No credit card required

Ready to Transform
Your Content?

Get ahead of other AI engineers with simply better content extraction