DSH's built-in web_fetch returns raw server HTML. That's fine for static pages, but it breaks for anything client-rendered or behind a login. I kept hitting this wall, so I built a plugin to fix it.
What it does:
-
moli_fetch— renders pages in a headless browser, returns text / markdown / html / screenshot / pdf. Supports CSS selector extraction so you don't dump the entire page into context. -
moli_probe— environment probing and browser engine installation.
Plugin itself is 26 kB. The browser engine is ~101 MB and installed separately. Works on Windows / macOS / Linux.
Why I built this
If you've used DSH's web_fetch on a React or Vue app, you know the problem: you get a shell of a page with empty divs. The actual content is rendered client-side, so it's never in the HTML response. Same issue with anything behind a login wall.
I wanted something that would render the page first, then let me grab what I need — without pulling the entire DOM into context.
How moli_fetch works
The tool launches a headless browser, waits for the page to finish rendering, then returns the result in the format you specify:
text — plain text extraction
markdown — useful for feeding into an LLM context
html — full rendered HTML if you need the structure
screenshot — PNG of the rendered page
pdf — full page export
You can also pass a CSS selector to extract only a specific element. If you just need one field from a page, you don't have to dump the whole thing.
Two Windows sandbox traps I ran into
The most time-consuming part of this project was dealing with two Windows-specific issues that only show up in sandboxed environments.
Pipe capture fails
In the Windows sandbox, child processes can't open inherited named pipes. When you set stdio: 'pipe' on a spawn call, you get status=null and zero bytes back. The workaround was to redirect output to a temp file instead of relying on pipes.PowerShell UTF-16 byte pollution
When you use PowerShell's > redirection on native program output, PowerShell re-encodes it as UTF-16, inserting a 00 byte after every single byte. This corrupts binary output completely — PNGs come out unreadable. The fix was to bypass PowerShell redirection entirely and use Node's own file streams.
Both of these are documented in the README and in the code comments, in case anyone else hits them.
What's in the box
The plugin is intentionally small (26 kB) because the browser engine is a separate ~101 MB download. moli_probe handles the installation, checks for existing installations, and reports what it finds.
The README covers:
Install paths for Windows, macOS, and Linux
Failure diagnostics and troubleshooting
Why the engine isn't bundled (size, licensing, platform differences)
TLS handling and why insecureTls defaults to true in some environments
Links
GitHub: https://github.com/27painter/dsh-moli
README: full install guide and troubleshooting
If you've been fighting with web_fetch on SPA or auth-gated pages, give it a shot. Feedback and issues welcome.
Install:
bash
dsh plugin --profile web add github:27painter/dsh-moli
# then call moli_probe action=install for the browser engine

Top comments (0)