API Documentation
Welcome to the MarkShot API documentation. Learn how to convert any webpage to clean, AI-friendly markdown with a single API call.
Introduction
MarkShot provides a simple REST API that converts webpages into clean, structured Markdown. Our service handles headless browser rendering, content extraction, and noise removal so you get pure, LLM-ready content.
Key features:
- JavaScript rendering — Full Chromium-based rendering for dynamic content
- Smart cleanup — Automatic removal of scripts, styles, SVGs, and boilerplate
- Fast processing — Most pages processed in under 3 seconds
- Simple pricing — Pay-as-you-go with no monthly fees
Registration
To use the MarkShot API, you'll need to create an account and generate an API key.
Create an account
Sign up at markshot.dev/accounts/signup/ with your email address. You'll receive {{ DEFAULT_CREDITS }} free credits to get started.
Verify your email
Check your inbox for a verification email and click the link to activate your account.
Generate an API key
Once verified, go to your API Keys dashboard and create a new key. Keep this key secure — it grants access to your account.
Important: You cannot create API keys until your email is verified. Check your spam folder if you don't see the verification email.
Quickstart
Here's the fastest way to make your first API request:
curl -X POST https://api.markshot.dev/v1/scrape \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com"}'
That's it! The API will return the page content as clean Markdown.
Authentication
All API requests require authentication using a Bearer token in
the Authorization header:
Authorization: Bearer YOUR_API_KEY
You can create and manage API keys from your dashboard. Each key has full access to your account, so keep them secure and rotate them if compromised.
Tip: Store your API key in an environment variable rather than hardcoding it in your source code.
Scrape Endpoint
The scrape endpoint converts a webpage URL into Markdown.
Request Parameters
Send a JSON body with the following parameters:
| Parameter | Type | Description |
|---|---|---|
url
required
|
string | The full URL of the webpage to scrape. Must include the protocol (http:// or https://). |
timeout
optional
|
integer | Maximum time in seconds to wait for the page to load. Default: 30. Range: 1-300. |
retries
optional
|
integer | Number of times to retry if the scrape fails. Default: 0. Range: 0-5. |
retry_delay
optional
|
integer | Seconds to wait between retries. Default: 10. Range: 5-30. |
Response Format
Successful responses return JSON with the following structure:
{
"success": true,
"url": "https://example.com",
"markdown": "# Example Domain\n\nThis domain is for use in illustrative examples...",
"duration_seconds": 1.523
}
Response Fields
| Field | Type | Description |
|---|---|---|
success |
boolean | Whether the scrape was successful. |
url |
string | The URL that was scraped (may differ from input if redirected). |
markdown |
string | The extracted content in Markdown format. |
duration_seconds |
float | Time taken to process the request in seconds. |
Code Examples
Here are complete examples in popular languages:
# Basic request curl -X POST https://api.markshot.dev/v1/scrape \ -H "Authorization: Bearer $MARKSHOT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "timeout": 60 }'
import httpx import os API_KEY = os.environ.get("MARKSHOT_API_KEY") API_URL = "https://api.markshot.dev/v1/scrape" def scrape_to_markdown(url, timeout=30): response = httpx.post( API_URL, headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" }, json={ "url": url, "timeout": timeout } ) response.raise_for_status() return response.json() # Example usage result = scrape_to_markdown("https://example.com") print(result["markdown"])
// Browser / Frontend JavaScript const API_KEY = 'your_api_key'; // Don't expose in frontend! async function scrapeToMarkdown(url) { const response = await fetch('https://api.markshot.dev/v1/scrape', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ url }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); } // Example usage const result = await scrapeToMarkdown('https://example.com'); console.log(result.markdown);
// Node.js with built-in fetch (Node 18+) const API_KEY = process.env.MARKSHOT_API_KEY; async function scrapeToMarkdown(url, options = {}) { const response = await fetch('https://api.markshot.dev/v1/scrape', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ url, ...options }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Request failed'); } return data; } // Example usage const result = await scrapeToMarkdown('https://example.com', { timeout: 60, retries: 2 }); console.log(result.markdown);
Error Codes
The API uses standard HTTP status codes to indicate success or failure:
OK
Request successful. The response body contains the scraped Markdown content.
Bad Request
Invalid request parameters. Check that
url is provided and properly formatted with
a valid protocol (http:// or https://).
Unauthorized
Missing or invalid API key. Ensure you're including the
Authorization: Bearer YOUR_API_KEY header.
Insufficient Credits
Your account has run out of credits. Purchase more credits to continue using the API.
Too Many Requests
You have too many concurrent scrape jobs in flight. Wait
for some to complete before submitting new requests. The
response includes a Retry-After header.
Internal Server Error
Something went wrong on our end. Try again later or contact support if the issue persists.
Error Response Format
Error responses include a JSON body with details:
{
"success": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Your account has 0 credits remaining. Please purchase more credits to continue."
}
}
Troubleshooting
Common Issues
Empty or incomplete content? Some pages
load content dynamically with JavaScript. Try increasing
the timeout parameter to give the page more
time to fully render before scraping.
Getting 429 errors? You have too many concurrent requests. MarkShot processes requests asynchronously — wait for current jobs to complete before submitting more. Consider adding a small delay between requests.
Can't create API keys? Make sure you've verified your email address. Check your spam folder for the verification email, or request a new one from the dashboard.
Scrape taking too long? Complex pages with lots of JavaScript may take longer to process. If a request times out, try again — our workers will retry failed jobs automatically.
FAQ
Each successful scrape costs 1 credit. Failed scrapes (due to invalid URLs, timeouts, etc.) do not consume credits.
No, credits never expire. Use them whenever you need.
We can handle pages up to 10MB in size. For larger pages, we'll return the content we were able to extract before hitting the limit.
Currently, we only support publicly accessible pages. Pages behind authentication or paywalls cannot be scraped.
You can have up to 10 concurrent scrape jobs in flight at any time. If you need higher limits, contact us to discuss enterprise options.
Yes! We offer full refunds on unused credits, no questions asked. Contact support to request a refund.
Curl only fetches raw HTML, it can't execute JavaScript. Modern websites render content dynamically with React, Vue, Next.js, etc. You'll get an empty shell or loader placeholders. MarkShot uses headless Chromium to fully render pages, then strips scripts, styles, and boilerplate to give you clean Markdown ready for LLMs.
You could run headless Chrome yourself, but then you need to: set up and maintain Chromium, handle browser crashes and memory leaks, write HTML-to-Markdown conversion logic, implement retry handling, and scale your infrastructure. MarkShot abstracts all of that into a single API call. One POST request, clean Markdown back.
Simpler and more focused. MarkShot does
one thing well: convert URLs to Markdown. No crawling
engines, no data pipelines, no compute credits or
monthly subscriptions. Pay-as-you-go credits that never
expire, full refunds on unused credits, and a single
/v1/scrape
endpoint. If you need markdown for AI/RAG pipelines
without the complexity, that's us.
Need Help?
Can't find what you're looking for? Our team is here to help.