← All posts

Get a Screenshot and Markdown in One API Request

Quick answer: A rendering API can return both a screenshot and the page's content as markdown from a single request, because it already loaded the page in a real browser to produce either one. You can DIY this with Playwright in about 20 lines, or make one API call and skip running browser infrastructure. If you're feeding vision models or archiving pages, getting both at once is the right default.

Screenshots and text extraction are usually treated as separate problems with separate tools. That's a historical accident. Both require the same expensive step, rendering the page in a real browser, so doing them in one pass is strictly cheaper than doing them in two.

Why You'd Want Both at Once

The pairing sounds niche until you hit one of these use cases, and then it's obviously the right shape:

Feeding vision models. Multimodal LLMs like Claude and GPT-4o can read screenshots directly. But a screenshot alone loses the links, the exact text, and everything below the fold. Sending the model both the image and the markdown gives it layout context plus precise, quotable text. In my experience this combination noticeably beats either input alone for tasks like "is this pricing table showing the right numbers."

Visual QA and monitoring. You want to know both what the page said and what it looked like. A price change is text. A broken hero image or an overlapping cookie banner is visual. One request, both signals, and they're guaranteed to come from the same page load, so you never wonder whether the text and the image reflect different states.

Archiving and compliance. If you need to prove what a page displayed at a point in time, a screenshot is the human-credible evidence and the markdown is the searchable record. Capturing them in separate requests minutes apart weakens that story, because dynamic pages can change between loads.

Content pipelines with a human in the loop. Reviewers approve faster when they can glance at the page image instead of parsing extracted text and imagining the layout.

The DIY Route: Playwright

Here's the honest version first: this is not hard to prototype. Playwright can give you a screenshot and the rendered HTML in one page load:

from playwright.sync_api import sync_playwright
from markdownify import markdownify

with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1280, "height": 800})
    page.goto("https://example.com/product/widget", wait_until="networkidle")

    png = page.screenshot(full_page=True)
    html = page.content()
    markdown = markdownify(html)

    with open("page.png", "wb") as f:
        f.write(png)
    with open("page.md", "w") as f:
        f.write(markdown)

    browser.close()

Twenty lines, works on your laptop, done. So why would anyone pay for an API?

Because the prototype is not the product. Running this in production means: keeping Chromium alive and patched in a container, handling pages that never reach networkidle, dismissing cookie banners that cover half your screenshot, dealing with sites that block datacenter IPs, cleaning nav and footer junk out of the markdown (raw markdownify output on a real site is rough), and scaling browser instances, which are memory-hungry, when traffic spikes. Each of those is a small project. Together they're someone's job.

The One-Call Route

A hosted rendering API does the browser work server-side and hands you both artifacts:

curl "https://link.sc/v1/fetch?url=https://example.com/product/widget&screenshot=true" \
  -H "Authorization: Bearer lsc_your_key"

The response includes the page as clean markdown, structured metadata, and the screenshot, so a single call replaces the whole Playwright stack:

{
  "url": "https://example.com/product/widget",
  "markdown": "# Widget Pro\n\nThe Widget Pro is our flagship...",
  "screenshot": "https://link.sc/renders/a1b2c3.png",
  "metadata": {
    "title": "Widget Pro | Example Store",
    "fetched_at": "2026-07-18T14:02:11Z"
  }
}

The markdown side matters as much as the screenshot side. Getting main-content extraction right, dropping navigation, ads, and boilerplate while keeping tables and code blocks, is the difference between markdown you can feed straight to an LLM and markdown you need to post-process. Full details are in the docs.

Feeding Both to a Vision Model

Here's the pattern I use for visual QA with Claude, combining both outputs from one fetch:

import anthropic, requests, base64

resp = requests.get(
    "https://link.sc/v1/fetch",
    params={"url": "https://example.com/pricing", "screenshot": "true"},
    headers={"Authorization": "Bearer lsc_your_key"},
).json()

image_b64 = base64.b64encode(
    requests.get(resp["screenshot"]).content
).decode()

client = anthropic.Anthropic()
answer = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": [
            {"type": "image", "source": {"type": "base64",
             "media_type": "image/png", "data": image_b64}},
            {"type": "text", "text":
             f"Page text:\n{resp['markdown']}\n\n"
             "Does the visible pricing match the text? "
             "Any layout problems like overlapping elements?"},
        ],
    }],
)
print(answer.content[0].text)

The model checks the image against the text from the same page load. That "same page load" guarantee is the quiet killer feature; with two separate tools you can't promise it.

When DIY Actually Makes Sense

I'll argue against my own product here, because the honest answer builds more trust than the salesy one:

Situation Recommendation
Prototype, internal tool, under ~100 pages/day DIY Playwright is fine
You already run browser infra for other reasons Add screenshots to it, don't pay twice
Sites that block datacenter IPs or need JS heavy lifting Hosted API
Production pipeline where uptime is your problem Hosted API
You need both artifacts atomically from one load Hosted API, or careful DIY

The crossover point is when browser maintenance starts eating engineering days. For most teams that happens embarrassingly fast, usually the first time a target site changes something and the pipeline breaks on a weekend. If you're not sure which category your target sites fall into, how to tell which scraping method a site needs walks through the diagnosis.

A Quick Note on Playing Fair

Screenshots don't change the etiquette of fetching. Stick to public pages, respect robots.txt, keep request rates polite, and don't use rendering to capture content behind logins you weren't given. Everything in how to avoid IP bans when scraping applies here too, and most of it boils down to behaving like a considerate visitor.

The Bottom Line

If your pipeline needs to know what a page looked like and what it said, stop making two requests to two systems. Render once, capture both. DIY it with Playwright if your scale is small and your targets are friendly; use a one-call API when reliability, blocked IPs, or clean extraction start costing you real time.


Need screenshots and clean markdown from any URL? link.sc returns both in one request. Start free with 500 credits a month.