What Lynx Is — and Why It’s Still Worth Your Time
Lynx is a fully featured text-based web browser that has been in continuous development since 1992. It renders no images, applies no CSS, executes no JavaScript. What it renders is your HTML — and nothing else.
In a modern workflow dominated by DevTools, Lighthouse scores, and automated accessibility checkers, Lynx sounds like an antique. It is, in the literal sense. But antiques sometimes reveal things that newer instruments miss. Lynx strips your interface down to its skeletal form and asks a single uncompromising question: does the structure of your document actually work?
The answer matters beyond the small population of people who browse text-only. Screen readers operate on the same underlying document structure that Lynx exposes. Search engine crawlers evaluate content hierarchy in terms that are structurally similar to what Lynx would parse. Users who disable JavaScript, or whose connections make it impractical to load large assets, encounter something close to what Lynx shows. Testing in Lynx is not an exercise in nostalgia — it is a fast, free structural audit of your HTML.
The Diagnostic Value: What Lynx Actually Exposes
Running a page through Lynx surfaces a specific class of problems that visual browsers actively conceal. CSS and JavaScript are extraordinarily good at papering over structural deficiencies. A heading hierarchy that jumps from H1 to H4 looks fine on screen; Lynx shows you exactly what it is. A navigation composed of div elements styled as a menu works fine visually; in Lynx, it may render as a block of meaningless text with no navigable anchors.
Here is what Lynx reveals, category by category:
Link text quality. Lynx displays links as they are written. If your codebase is full of “click here,” “read more,” and “learn more” anchors, Lynx makes this impossible to ignore. Every link on the page is navigable in sequence, and context-free labels are useless without the surrounding visual layout to give them meaning. What sounds defensible in a visual context — “click here to download the report” where “here” is in a sentence — becomes obviously broken when you are navigating a list of fifteen consecutive “click here” links by tab key.
Heading hierarchy. Lynx renders headings in sequence, making the document outline immediately legible. You can see instantly whether your H2s follow the H1, whether you have skipped levels, and whether decorative headings (styled large text that was marked up as H1 for visual impact) have wrecked the document structure. A well-ordered heading hierarchy in Lynx is one of the clearest indicators of an accessible page.
Form labels. Forms without properly associated labels — <label for> pointing to an input’s id, or inputs wrapped inside a <label> element — are among the most common accessibility failures on the web. In a visual browser, placeholder text and adjacent copy can make unlabeled forms feel usable. In Lynx, an unlabeled input field renders without any textual description. You see a form field. You do not know what it is for.
Alt text. Images in Lynx are replaced by their alt attribute value, or by [INLINE] if none is present. Pages that treat alt as optional clutter suddenly reveal what they are: documents with conspicuous gaps where content should be. Decorative images with empty alt attributes — correct practice — are simply not rendered, as intended. Meaningful images with empty or absent alt attributes are rendered as [INLINE], which tells the reader exactly nothing.
Content order without CSS. Visual layout can place content in any visual position regardless of its order in the source. CSS grid and flexbox make this trivially easy. Lynx exposes the source order. If your page places a sidebar before main content in the source — because it was easier to style that way — Lynx will read the sidebar first. Screen readers follow source order, not visual order. Lynx makes the source-order problem concrete and unavoidable.
Navigation structure. Lynx renders links as navigable items and lets you move between them with the tab key or arrow keys. A navigation composed of semantic <nav>, <ul>, and <a> elements works as expected. A navigation built from nested divs with click handlers may render as flat, unlinkable text, or may not render navigable links at all. The difference is unmistakable.
Installing and Running Lynx
On macOS, Homebrew is the path of least resistance:
brew install lynx
On Debian-based Linux distributions:
sudo apt-get install lynx
On Windows, precompiled binaries are available from the Lynx development site at lynx.invisible-island.net. Alternatively, Lynx is available within WSL using the same apt-get command above.
To test a live URL, pass it directly as an argument:
lynx https://example.com
To test a local file:
lynx /path/to/your/file.html
Within Lynx, basic navigation is as follows: arrow keys move between links; Enter follows a link; Backspace or the left arrow key goes back; g opens a Go To URL prompt; q quits. Pressing Tab jumps forward through links, which is the most useful motion for auditing link text.
The --dump flag outputs the rendered text directly to the terminal without the interactive browser, useful for scripting or piping into a file for review:
lynx --dump https://example.com
A Before and After: Form Labels
The difference between a form that works in Lynx and one that does not is structural, not visual. Here is the pattern that fails:
<!-- Before: placeholder as label substitute -->
<div class="field">
<input type="email" placeholder="Your email address" name="email">
</div>
<div class="field">
<input type="text" placeholder="Your name" name="name">
</div>
In Lynx, this renders as two unlabeled input fields. The placeholder text does not appear in the rendered output. A user — or a screen reader — encounters two anonymous form fields with no indication of their purpose.
The corrected version:
<!-- After: explicit label association -->
<div class="field">
<label for="email">Email address</label>
<input type="email" id="email" name="email" placeholder="you@example.com">
</div>
<div class="field">
<label for="name">Your name</label>
<input type="text" id="name" name="name" placeholder="First and last name">
</div>
In Lynx, the label text appears immediately before each input field, making the form fully usable without visual context. The placeholder is still there for visual browsers. This version also works correctly with screen readers, passes WCAG 1.3.1 (Info and Relationships), and costs nothing in visual design — the label can be styled however the design requires.
The pattern scales to every form element: <select>, <textarea>, radio groups wrapped in <fieldset> with a <legend>. The rule is the same: every interactive field needs a programmatically associated label.
A Practical Testing Checklist
When auditing a page in Lynx, work through these checks in order:
Read the page top to bottom. Does the content make sense without images or layout? Is the most important content near the top in source order?
Tab through all links. Is every link’s text descriptive without context? If you read each link in isolation — as a screen reader user navigating by links would — do you know what each one does?
Review the heading structure. Does the page have one H1? Do H2s follow the H1 logically? Are there skipped heading levels (H1 → H4)?
Submit or interact with every form. Are all fields labeled? Are error messages associated with their fields? Does the form work without JavaScript?
Check image placeholders. Are
[INLINE]markers appearing where meaningful images should be described? Are decorative images correctly suppressed (empty alt, no[INLINE]marker)?Navigate the primary navigation. Is it reachable and usable? Are there skip links that work in Lynx?
Check the page title. It appears at the top of the Lynx rendering. Is it descriptive and unique?
The Connection to Screen Reader Behavior
Lynx and screen readers are not the same thing, and Lynx testing does not substitute for testing with NVDA, VoiceOver, or JAWS. But they share a common dependency: both operate on the semantic structure of your HTML rather than its visual presentation.
A screen reader user navigating by headings requires the same well-ordered heading hierarchy that Lynx exposes. A screen reader user navigating by links requires the same descriptive link text that Lynx makes visible. A screen reader user filling out a form requires the same label associations that Lynx renders as field descriptions. The problems Lynx surfaces are the same problems that make screen readers harder to use.
This is not a coincidence. It is a property of the web’s underlying model. HTML encodes meaning. CSS and JavaScript modify presentation and behavior. When the semantic layer is strong, the presentation and behavior layers can be added safely, incrementally, and in a way that degrades gracefully when those layers are unavailable. When the semantic layer is weak, everything built on top of it is built on unstable ground.
Progressive Enhancement as a Design Discipline
The traditional framing of progressive enhancement focuses on reliability and reach: start with a baseline experience that works everywhere, then enhance. That framing remains correct, but there is a complementary way to think about it.
Testing in Lynx is a forcing function for progressive enhancement because it makes the baseline experience visible. You cannot look at your page in Lynx and avoid the question of whether the HTML layer is actually doing its job. Visual browsers let you sidestep that question indefinitely. Lynx does not.
The discipline this creates is valuable beyond Lynx itself. Developers who habitually consider the semantic layer of their work tend to write HTML that is more maintainable, more consistent, and easier to update. Component systems built on semantic foundations are easier to reason about. The heading hierarchy in a design system is clearer when someone has actually audited it. Form patterns are more consistent when labeled form fields are the default rather than an afterthought.
None of this requires that you ship a Lynx-optimized experience or that you think about users who browse text-only. It requires that you use Lynx as a diagnostic instrument — a way of seeing your own work that your usual tools make difficult.
The Standard Worth Holding
The goal is not Lynx compatibility for its own sake. The goal is HTML that communicates meaning, navigation that works without JavaScript, forms that are usable without visual context, and content that reads clearly in source order. Lynx compatibility is the byproduct of achieving that goal.
If a page works well in Lynx — if the links are descriptive, the headings are ordered, the forms are labeled, the content makes sense — you have strong evidence that the document structure is sound. That structure is what screen readers navigate, what search engines index, and what users with assistive technology experience every day. It is also what remains when the network is slow, the script fails to load, or the CSS is blocked by a corporate proxy.
Testing in Lynx takes minutes. The structural improvements it prompts last as long as the page does. That is a favorable exchange.



