Blog · 2026-08-27 · Vynaris Team
Accept: text/markdown cut one page from 9,020 to 539 input tokens
Accept: text/markdown cut a live page from 9,020 to 539 input tokens. Three-site measurements and cost math, verified 2026-08-27.
On acceptmarkdown.com, content negotiation cut the exact response body from 24,214 to 2,201 bytes. OpenAI's counter measured 9,020 versus 539 input tokens, a 94.0244% cut. On GPT-5.6 Luna, 1,000 fetches fall from $1.8040 to $0.1078. Prices verified 2026-08-27.
TL;DR
- Across three live pages, HTML totaled 200,400 bytes and 73,915 tokens. Negotiated Markdown totaled 9,381 bytes and 2,460 tokens. That is 95.3189% fewer bytes and 96.6719% fewer tokens.
- The headline page fell from 9,020 to 539 tokens. At current input rates, its bill per 1,000 fetches falls by $1.6962 on GPT-5.6 Luna, $16.9620 on GPT-5.6 Terra and $33.9240 on GPT-5.6 Sol.
- This only works when the client asks for Markdown and the origin serves a faithful representation. If your agent already strips HTML deterministically, content negotiation may save little.
Verdict table
Live page HTML bytes Markdown bytes HTML tokens Markdown tokens Token cut
------------------------------------------------------ ----------- -------------- ----------- --------------- ------------
[acceptmarkdown.com home](https://acceptmarkdown.com/) 24,214 2,201 9,020 539 94.0244%
[roots.io home](https://roots.io/) 100,497 5,914 43,788 1,642 96.2501%
[accept.md docs](https://www.accept.md/docs) 75,689 1,266 21,107 279 98.6782%
**Three-page total** **200,400** **9,381** **73,915** **2,460** **96.6719%**The smallest measured cut was still 94.0244%. This is not a bytes-to-tokens estimate. Each exact UTF-8 body went through the provider's input-token counting endpoint.
What we measured
We fetched each canonical URL twice on 2026-08-27. The first request sent Accept: text/html. The second sent Accept: text/markdown. We archived both response bodies, their SHA-256 hashes, content types and observed Vary headers.
We then sent every body as plain input to OpenAI's documented `POST /responses/input_tokens` endpoint. We repeated the count for GPT-5.6 Luna, GPT-5.6 Terra and GPT-5.6 Sol. All three returned the same counts for these bodies.
That endpoint includes the request wrapper used by a plain text input. The wrapper is present on both representations, so we did not subtract it. We also did not clean the HTML before counting it. This comparison prices what happens when an agent inserts the raw fetched body into its prompt.
The test measures page input only. It excludes instructions, conversation history, tool schemas, output tokens and the model's response. Those costs do not change merely because the page arrived as Markdown.
The aggregate arithmetic is explicit:
HTML bytes = 24,214 + 100,497 + 75,689 = 200,400
Markdown bytes = 2,201 + 5,914 + 1,266 = 9,381
Byte cut = (200,400 - 9,381) / 200,400 = 95.3189%
Token cut = (73,915 - 2,460) / 73,915 = 96.6719%
Cost per 1,000 fetches of the headline page
OpenAI's live API pricing lists short-context input at $0.20 per 1M tokens for GPT-5.6 Luna, $2.00 for GPT-5.6 Terra and $4.00 for GPT-5.6 Sol. The 9,020-token HTML and 539-token Markdown bodies remain far below the listed long-context boundary, so short-context rates apply.
Model Input price / 1M HTML per fetch / per 1k Markdown per fetch / per 1k Saving / 1k
------------- ---------------- ----------------------- --------------------------- -----------
GPT-5.6 Luna $0.20 $0.001804 / $1.8040 $0.0001078 / $0.1078 $1.6962
GPT-5.6 Terra $2.00 $0.01804 / $18.0400 $0.001078 / $1.0780 $16.9620
GPT-5.6 Sol $4.00 $0.03608 / $36.0800 $0.002156 / $2.1560 $33.9240The Luna HTML line is 9,020 × $0.20 / 1,000,000 = $0.001804 per fetch. Multiply by 1,000 for $1.8040. The Markdown line replaces 9,020 with 539. Every other cell uses the same formula and its listed input rate.
Put your own measured count and call volume into the calculator. Do not copy our page shape into a budget for a different site.
Why 90.9102% fewer bytes became 94.0244% fewer tokens
Bytes and tokens are different units. The HTML body contains tags, attribute names, class strings, scripts, styles and repeated layout markup. A tokenizer can split that syntax into many short pieces. Clean prose often packs more bytes into each token.
On the headline page, HTML used 24,214 bytes and 9,020 tokens, or 2.6845 bytes per token. Markdown used 2,201 bytes and 539 tokens, or 4.0835 bytes per token. The body became smaller, and its remaining text tokenized more efficiently.
The other pages followed the same direction. roots.io dropped 94.1152% by bytes and 96.2501% by tokens. accept.md docs dropped 98.3274% by bytes and 98.6782% by tokens. None of those relationships should be generalized into a universal conversion ratio. Measure the exact content with the exact model endpoint.
Our earlier web-data extraction cost playbook assumed consumer-side boilerplate stripping. This test is different. The server removes the waste before the response crosses the network or enters an agent's context. The coding-agent scaffolding analysis covers a second source of input bloat after page retrieval.
A production-safe implementation
Generate HTML and Markdown from one content source. Do not scrape your rendered HTML on every request unless you have measured the CPU and latency cost. Build-time dual rendering is easier to cache and easier to test.
At request time, use a standards-aware negotiator. Substring matching fails on headers such as text/markdown;q=0, text/html;q=1, where the client explicitly refuses Markdown. The handler needs this decision flow:
parse Accept media ranges and q-values
score text/markdown and text/html
if Markdown scores higher: return Markdown
if HTML scores at least as high: return HTML
if neither is acceptable: return 406
on both successful responses: append Vary: AcceptKeep HTML as the tie-breaker. Browsers often send broad ranges, and a wildcard is not a request to show raw Markdown to a human.
The response contract is small:
HTTP/1.1 200 OK
Content-Type: text/markdown; charset=utf-8
Vary: Accept
Cache-Control: public, max-age=300Vary: Accept tells shared caches that one URL has multiple representations. Without it, an agent can prime a cache with Markdown and the next browser can receive that body, or the reverse.
Our live check found the correct Markdown content type on all three pages. acceptmarkdown.com and roots.io returned Vary: Accept on the Markdown response. accept.md docs returned Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch in our request, without Accept. Its token reduction is real, but the observed cache contract needs attention.
Keep the two representations equivalent
The cheapest response is useless when it silently drops the answer. Treat Markdown as another production rendering target, not as a lossy export someone runs once.
Start from the same article record, documentation AST or CMS document. Render headings, paragraphs, lists, links, images and code into both targets. Preserve image alt text and table headers. Keep canonical links identical. If a component has no honest Markdown equivalent, state that omission in the Markdown body instead of deleting it invisibly.
Add parity fixtures for content that tends to break: nested lists, fenced code, tables with empty cells, footnotes and inline links. The test does not need pixel equality. It needs semantic equality. A practical assertion checks that required headings, URLs, code fragments and data fields appear in both outputs.
Do not generate Markdown by fetching your own public HTML during every agent request. That adds a network hop and repeats parsing work. Prefer source-driven or build-time rendering. Runtime conversion can still make sense for legacy pages, but cache the result and invalidate it with the source document.
Roll out by route class. Documentation, articles and changelogs usually have clean text structure. Interactive applications and account pages often do not. A blanket middleware that converts every HTML response can turn forms, dashboards and client-rendered data into empty shells.
Finally, keep representation selection separate from crawler detection. User-agent allowlists age badly. The Accept header states what the client can consume, while the URL continues to identify the resource. That makes the behavior testable with curl and available to any compatible agent.
What the dollar table leaves out
The table isolates model input fees because that is the cost changed by response size. It does not price CDN transfer, origin rendering, HTML cleanup, embeddings, model output or retries. Those belong in a full pipeline bill.
The missing items can move in opposite directions. A smaller body lowers network transfer and parsing work. A runtime converter adds CPU time. Cleaner text may improve retrieval, but the current experiment did not run a retrieval benchmark. We therefore claim measured token and input-fee reductions, not better answers.
The same boundary applies to prompt caching. A fetched page that repeats across requests may qualify for a discounted cache-read rate. A page that changes often may not. Content negotiation reduces the body before either case, so calculate cache economics after measuring the negotiated representation.
Test the contract, not the happy path
Four requests catch most broken implementations:
Request header Expected result
------------------------------------------ ----------------------------------------------------
`Accept: text/markdown` Markdown body, Markdown content type, `Vary: Accept`
`Accept: text/html` HTML body, HTML content type, `Vary: Accept`
`Accept: text/markdown;q=0, text/html;q=1` HTML, because Markdown is refused
`Accept: image/png` `406 Not Acceptable` when no supported range matchesRun the pair below against every route class, not only the home page:
curl -sS -D - -o /dev/null -H 'Accept: text/markdown' "$ARTICLE_URL"
curl -sS -D - -o /dev/null -H 'Accept: text/html' "$ARTICLE_URL"Then test through the CDN. An origin can behave correctly while an edge cache ignores the response's variation key. Verify content type and body after both request orders: HTML then Markdown, and Markdown then HTML.
Honest tradeoff: negotiation can duplicate work
Do not ship this because a 96.6719% aggregate looks exciting. Ship it when the agent consumes raw or lightly processed responses and your Markdown preserves the information it needs.
If your crawler already runs deterministic readability extraction, the effective cost per token may already resemble the Markdown case. Adding a second representation then creates templates, cache rules and regression tests without removing many more tokens.
Markdown can also discard useful structure. Complex tables, image alt text, code annotations, form labels and embedded metadata may survive poorly. A 279-token page that omits the field your agent needed is not cheaper. It is a failed fetch.
Compare task success before and after the change. Token savings are only valid while the answer, extraction or retrieval result remains acceptable.
Where Vynaris fits
Model routing cannot repair a bloated response. Remove deterministic waste first. Then choose a model for the 539 useful tokens that remain.
Vynaris can price and route that compact request across providers, but it should not sit in front of a preventable HTML tax and pretend model choice is the main lever. Content negotiation belongs at the origin. Routing starts after preprocessing.
FAQ
How much did `Accept: text/markdown` reduce input tokens? The measured cuts were 94.0244%, 96.2501% and 98.6782% across three live pages. The combined count fell from 73,915 to 2,460 tokens, a 96.6719% reduction.
Does a 90.9102% byte cut mean a 90.9102% token cut? No. On the headline page, 90.9102% fewer bytes became 94.0244% fewer provider-counted tokens. HTML syntax and clean prose tokenize differently.
How much does the headline page cost per 1,000 model fetches? At verified short-context input rates, HTML costs $1.8040 on GPT-5.6 Luna, $18.0400 on GPT-5.6 Terra and $36.0800 on GPT-5.6 Sol. Negotiated Markdown costs $0.1078, $1.0780 and $2.1560.
Is `Content-Type: text/markdown` enough? No. Keep the HTML variant, honor q-values, return an unsatisfied response when appropriate and include Vary: Accept so shared caches separate representations.
Should every site add Markdown negotiation? No. It pays when agents ingest raw pages repeatedly. If clients already strip boilerplate, or Markdown loses required structure, keep the simpler pipeline.
Sources and reproduction
- Live response pairs: acceptmarkdown.com, roots.io and accept.md docs, captured 2026-08-27.
- OpenAI input-token counting endpoint, request and response schema, verified 2026-08-27: https://developers.openai.com/api/reference/typescript/resources/responses/subresources/input_tokens
- OpenAI API pricing and current GPT-5.6 model IDs, verified 2026-08-27: https://developers.openai.com/api/docs/pricing
- Reproducible arithmetic:
artifacts/accept-text-markdown-90-percent-byte-cut-llm-cost-math-math.py. - Raw token-count responses:
artifacts/accept-text-markdown-90-percent-byte-cut-llm-cost-math-token-counts.json.
Prices change. Re-run the source fetch and math scripts before using these dollar figures in a budget.