curl that reads the page for you
See the code
curl that reads the page for you.
Tell it what you want. It picks it out of the page.
$ jurl -q "how do I install it on macOS?" github.com/BurntSushi/ripgrep
…
### Installation
…
If you're a macOS Homebrew or a Linuxbrew user, then you can install ripgrep from homebrew-core:
```
$ brew install ripgrep
```
If you're a MacPorts user, then you can install ripgrep from the official ports:
```
$ sudo port install ripgrep
```
$ jurl --find "a cathedral" en.wikipedia.org/wiki/Cologne
https://thumb.wikimedia.org/wikipedia/commons/thumb/2/27/Kdom.jpg/250px-Kdom.jpg
$ jurl --links -n 3 news.ycombinator.com
https://github.com/PowderworksCode/headstart
https://www.da.vidbuchanan.co.uk/blog/hacking-time.html
https://gamehistory.org/5k-magazines/
brew install rayoplateado/tap/jurl # macOS, Linux
curl -LsSf https://github.com/rayoplateado/jurl/releases/latest/download/jurl-installer.sh | sh # no Homebrew
Windows: powershell -ExecutionPolicy Bypass -c "irm https://github.com/rayoplateado/jurl/releases/latest/download/jurl-installer.ps1 | iex" · From source: cargo install --git https://github.com/rayoplateado/jurl
Then run it. The first time, jurl asks for a TypeSafe API key, checks it and saves it. That's the whole setup. Pages that need JavaScript just work too: jurl fetches a headless browser the first time one shows up.
To use --vision and --find, run jurl init and add a Cloudflare Workers AI token.
$ jurl -n 3 blog.cloudflare.com/markdown-for-agents/
# Introducing Markdown for Agents
<https://blog.cloudflare.com/markdown-for-agents/> · article (1.00)
The way content and businesses are discovered online is changing rapidly. In the past, traffic originated from traditional search engines, and SEO determined who got found first. …
## Convert HTML to markdown, automatically
Cloudflare's network now supports real-time content conversion at the source, …
Here’s how it works. To fetch the markdown version of any page from a zone with Markdown for Agents enabled, the client needs to add the **Accept** negotiation header …
You get the title, what kind of page it is, and the blocks that carry it, in reading order. Navigation, cookie banners, sign-up prompts, author bios and footers are left out.
$ jurl -q "What is the Jevons paradox?" -n 2 en.wikipedia.org/wiki/William_Stanley_Jevons
…
Jevons received public recognition for his work on The Coal Question (1865), in which he called attention to the gradual exhaustion of Britain's coal supplies and also put forth the view that increases in energy production efficiency leads to more, not less, consumption. …
## Practical economics
In The Coal Question, Jevons covered a breadth of concepts on energy depletion …
Out of a page with about 240 blocks, you get the two paragraphs that answer it.
$ jurl --code -n 2 github.com/BurntSushi/ripgrep
### Installation
```
$ brew install ripgrep
```
```
$ cargo install ripgrep
```
$ jurl --links -n 3 -q "official installation instructions" github.com/BurntSushi/ripgrep
https://www.macports.org/ports.php?by=name&substr=ripgrep
https://packages.gentoo.org/packages/sys-apps/ripgrep
https://chocolatey.org/packages/ripgrep
The ranking puts content first, ahead of login, share or privacy policy. Add -q to keep only the links about something specific.
--image picks the content images by their file name, alt text and caption, with no logos, icons or tracking pixels. --vision also has Clef look at the pixels, which matters when the alt text says nothing:
| Image on a Cloudflare blog post | Alt text | --image | --vision |
|---|---|---|---|
| Stacked area chart | BLOG-3162 4 | 0.64 | 0.82 |
| Diagram | BLOG-3162 3 | 0.63 | 0.82 |
| Author avatar | Will Allen | 0.38 | 0.21 |
| Company logo | Cloudflare | 0.09 | 0.08 |
$ jurl --find "a cathedral" -n 3 en.wikipedia.org/wiki/Cologne
The page has 73 images, and Clef looks at every one of them in parallel. It took 2.3 seconds:
| Image | Why it matched | p | |
|---|---|---|---|
| 1 | Kdom.jpg | Cologne Cathedral | 0.96 |
| 2 | Köln_um_1890.jpg | The 1890 skyline, the cathedral towering over it | 0.95 |
| 3 | Kranhäuser_Cologne_April_2018.jpg | The Rhine at dusk, the lit cathedral on the right. No alt text, no caption: only the pixels could find it | 0.95 |
If nothing matches, jurl tells you so instead of handing you the least-bad photo:
$ jurl --find "a carnival parade" en.wikipedia.org/wiki/Cologne
jurl: no image in https://en.wikipedia.org/wiki/Cologne looks like "a carnival parade" (closest: …, p=0.02)
Some pages arrive empty because their content is built by JavaScript. jurl spots those and renders them in Lightpanda, a fast headless browser:
$ jurl -n 2 hn.algolia.com
jurl: no text without JavaScript, rendering with Lightpanda…
# HN Search powered by Algolia
<https://hn.algolia.com/> · listing (1.00)
Stephen Hawking has died(http://www.bbc.com/news/uk-43396008)
6015 points|Cogito|9 years ago|436 comments
Use -r to force it.
Everything prints plain text or plain URLs, so jurl fits in a pipe:
# Read the top 3 Hacker News stories, one key paragraph each
jurl -l -n 3 news.ycombinator.com | xargs -n1 jurl -n 1
# Download the photo that matches
jurl -f "a bridge over a river" en.wikipedia.org/wiki/Cologne | xargs curl -sO
# Every chart in a post
jurl -f "a chart or graph" -n 10 blog.cloudflare.com/markdown-for-agents/ | xargs -n1 curl -sO
# Only the confident answers, for scripts
jurl --json -q "installation" github.com/BurntSushi/ripgrep | jq -r '.blocks[] | select(.p > 0.8) | .text'
| Flag | |
|---|---|
-q, --ask "…" | Keep what answers the question. Works with every mode |
-c, --code | Code blocks only |
-l, --links | Content links, best first |
-i, --image | Content images, judged by file name, alt text and caption |
--vision | Like --image, plus Clef looks at the pixels |
-f, --find "…" | The image that best matches the description |
-r, --render | Run the page's JavaScript first (automatic for empty JavaScript apps) |
-n, --max N | How many results (12 blocks, 5 with --ask, 8 code blocks, 20 links, 1 with --find) |
-a, --all | No limit: everything above the threshold |
--threshold P | Minimum probability (default 0.5) |
--json | Machine-readable output, with every probability |
-t, --timing | Where the time went, on stderr |
jurl init | Set or replace your API keys |
Keys live in ~/.config/jurl/env. Environment variables take precedence over that file: TYPESAFE_API_KEY, and for images CLOUDFLARE_ACCOUNT_ID plus CLOUDFLARE_AI_TOKEN.
| Command | Typical time | Typical cost |
|---|---|---|
jurl <url> | 0.6–1 s | $0.0004–0.0013 |
jurl -i <url> | 0.5–0.7 s | $0.00004 |
jurl --vision <url> | 1.3–1.9 s | $0.0002 |
jurl --find "…" <url> (73 images) | 2.2–2.9 s | $0.002 |
| JavaScript apps | +3–6 s | same |
Measured on 2026-10-04. Run any command with -t to see your own numbers.
jurl has no server and no account of its own. It talks to the model APIs directly with your keys:
--vision or --find, the images go to Cloudflare too. Keep that in mind for internal or private pages.brew upgrade jurl, or run the install script again.brew uninstall jurl, or delete ~/.local/bin/jurl. To remove everything, also delete ~/.config/jurl (keys) and ~/Library/Caches/jurl or ~/.cache/jurl (the browser).url ─▶ fetch (asks for markdown first) ─▶ split into blocks · links · images
└─ empty JavaScript app? ─▶ render in Lightpanda
│
one yes/no question per candidate
┌───────────┴───────────┐
▼ ▼
Jev reads text Clef looks at images
"is block 12 the point?" "does this show a cathedral?"
p = 0.97 p = 0.96
└───────────┬───────────┘
▼
rank · threshold · page order · print verbatim
text/markdown first; sites using Cloudflare's Markdown for Agents send it already converted. Otherwise jurl's own extractor drops navigation, footers, asides and scripts, and splits the rest into headings, paragraphs, list items, code, quotes and tables.xargs curl.--vision adds up the content classes and averages them with Jev's judgement of the page context: a portrait is content on Wikipedia and noise in an author box.--find, Clef decides alone. It sees the pixels and the alt text and caption.--vision fast:
PATH, jurl uses that. JURL_LIGHTPANDA points to a specific binary, and JURL_NO_DOWNLOAD stops the download. Lightpanda has no Windows build, so on Windows rendering is unavailable.cargo test # extraction: layout tables, lazy images, markdown, links, app-shell detection
cargo build --release && ./target/release/jurl -t <url>
| File | What's in it |
|---|---|
src/main.rs | Modes, chunking, hedging, output |
src/extract.rs | HTML and markdown → blocks, links, images |
src/decide.rs | Jev and Clef clients |
src/fetch.rs · src/lightpanda.rs | Fetching, rendering, the browser download |
src/setup.rs · src/config.rs | First-run key prompt, jurl init, key storage |
Releases are built by cargo-dist when a v* tag is pushed.
Issues and pull requests are welcome. Read CONTRIBUTING.md first; security problems go to SECURITY.md.
MIT or Apache-2.0, at your option. Lightpanda, which jurl downloads for JavaScript pages, is a separate program under AGPL-3.0.
curl that reads the page for you
See the code
curl that reads the page for you.
Tell it what you want. It picks it out of the page.
$ jurl -q "how do I install it on macOS?" github.com/BurntSushi/ripgrep
…
### Installation
…
If you're a macOS Homebrew or a Linuxbrew user, then you can install ripgrep from homebrew-core:
```
$ brew install ripgrep
```
If you're a MacPorts user, then you can install ripgrep from the official ports:
```
$ sudo port install ripgrep
```
$ jurl --find "a cathedral" en.wikipedia.org/wiki/Cologne
https://thumb.wikimedia.org/wikipedia/commons/thumb/2/27/Kdom.jpg/250px-Kdom.jpg
$ jurl --links -n 3 news.ycombinator.com
https://github.com/PowderworksCode/headstart
https://www.da.vidbuchanan.co.uk/blog/hacking-time.html
https://gamehistory.org/5k-magazines/
brew install rayoplateado/tap/jurl # macOS, Linux
curl -LsSf https://github.com/rayoplateado/jurl/releases/latest/download/jurl-installer.sh | sh # no Homebrew
Windows: powershell -ExecutionPolicy Bypass -c "irm https://github.com/rayoplateado/jurl/releases/latest/download/jurl-installer.ps1 | iex" · From source: cargo install --git https://github.com/rayoplateado/jurl
Then run it. The first time, jurl asks for a TypeSafe API key, checks it and saves it. That's the whole setup. Pages that need JavaScript just work too: jurl fetches a headless browser the first time one shows up.
To use --vision and --find, run jurl init and add a Cloudflare Workers AI token.
$ jurl -n 3 blog.cloudflare.com/markdown-for-agents/
# Introducing Markdown for Agents
<https://blog.cloudflare.com/markdown-for-agents/> · article (1.00)
The way content and businesses are discovered online is changing rapidly. In the past, traffic originated from traditional search engines, and SEO determined who got found first. …
## Convert HTML to markdown, automatically
Cloudflare's network now supports real-time content conversion at the source, …
Here’s how it works. To fetch the markdown version of any page from a zone with Markdown for Agents enabled, the client needs to add the **Accept** negotiation header …
You get the title, what kind of page it is, and the blocks that carry it, in reading order. Navigation, cookie banners, sign-up prompts, author bios and footers are left out.
$ jurl -q "What is the Jevons paradox?" -n 2 en.wikipedia.org/wiki/William_Stanley_Jevons
…
Jevons received public recognition for his work on The Coal Question (1865), in which he called attention to the gradual exhaustion of Britain's coal supplies and also put forth the view that increases in energy production efficiency leads to more, not less, consumption. …
## Practical economics
In The Coal Question, Jevons covered a breadth of concepts on energy depletion …
Out of a page with about 240 blocks, you get the two paragraphs that answer it.
$ jurl --code -n 2 github.com/BurntSushi/ripgrep
### Installation
```
$ brew install ripgrep
```
```
$ cargo install ripgrep
```
$ jurl --links -n 3 -q "official installation instructions" github.com/BurntSushi/ripgrep
https://www.macports.org/ports.php?by=name&substr=ripgrep
https://packages.gentoo.org/packages/sys-apps/ripgrep
https://chocolatey.org/packages/ripgrep
The ranking puts content first, ahead of login, share or privacy policy. Add -q to keep only the links about something specific.
--image picks the content images by their file name, alt text and caption, with no logos, icons or tracking pixels. --vision also has Clef look at the pixels, which matters when the alt text says nothing:
| Image on a Cloudflare blog post | Alt text | --image | --vision |
|---|---|---|---|
| Stacked area chart | BLOG-3162 4 | 0.64 | 0.82 |
| Diagram | BLOG-3162 3 | 0.63 | 0.82 |
| Author avatar | Will Allen | 0.38 | 0.21 |
| Company logo | Cloudflare | 0.09 | 0.08 |
$ jurl --find "a cathedral" -n 3 en.wikipedia.org/wiki/Cologne
The page has 73 images, and Clef looks at every one of them in parallel. It took 2.3 seconds:
| Image | Why it matched | p | |
|---|---|---|---|
| 1 | Kdom.jpg | Cologne Cathedral | 0.96 |
| 2 | Köln_um_1890.jpg | The 1890 skyline, the cathedral towering over it | 0.95 |
| 3 | Kranhäuser_Cologne_April_2018.jpg | The Rhine at dusk, the lit cathedral on the right. No alt text, no caption: only the pixels could find it | 0.95 |
If nothing matches, jurl tells you so instead of handing you the least-bad photo:
$ jurl --find "a carnival parade" en.wikipedia.org/wiki/Cologne
jurl: no image in https://en.wikipedia.org/wiki/Cologne looks like "a carnival parade" (closest: …, p=0.02)
Some pages arrive empty because their content is built by JavaScript. jurl spots those and renders them in Lightpanda, a fast headless browser:
$ jurl -n 2 hn.algolia.com
jurl: no text without JavaScript, rendering with Lightpanda…
# HN Search powered by Algolia
<https://hn.algolia.com/> · listing (1.00)
Stephen Hawking has died(http://www.bbc.com/news/uk-43396008)
6015 points|Cogito|9 years ago|436 comments
Use -r to force it.
Everything prints plain text or plain URLs, so jurl fits in a pipe:
# Read the top 3 Hacker News stories, one key paragraph each
jurl -l -n 3 news.ycombinator.com | xargs -n1 jurl -n 1
# Download the photo that matches
jurl -f "a bridge over a river" en.wikipedia.org/wiki/Cologne | xargs curl -sO
# Every chart in a post
jurl -f "a chart or graph" -n 10 blog.cloudflare.com/markdown-for-agents/ | xargs -n1 curl -sO
# Only the confident answers, for scripts
jurl --json -q "installation" github.com/BurntSushi/ripgrep | jq -r '.blocks[] | select(.p > 0.8) | .text'
| Flag | |
|---|---|
-q, --ask "…" | Keep what answers the question. Works with every mode |
-c, --code | Code blocks only |
-l, --links | Content links, best first |
-i, --image | Content images, judged by file name, alt text and caption |
--vision | Like --image, plus Clef looks at the pixels |
-f, --find "…" | The image that best matches the description |
-r, --render | Run the page's JavaScript first (automatic for empty JavaScript apps) |
-n, --max N | How many results (12 blocks, 5 with --ask, 8 code blocks, 20 links, 1 with --find) |
-a, --all | No limit: everything above the threshold |
--threshold P | Minimum probability (default 0.5) |
--json | Machine-readable output, with every probability |
-t, --timing | Where the time went, on stderr |
jurl init | Set or replace your API keys |
Keys live in ~/.config/jurl/env. Environment variables take precedence over that file: TYPESAFE_API_KEY, and for images CLOUDFLARE_ACCOUNT_ID plus CLOUDFLARE_AI_TOKEN.
| Command | Typical time | Typical cost |
|---|---|---|
jurl <url> | 0.6–1 s | $0.0004–0.0013 |
jurl -i <url> | 0.5–0.7 s | $0.00004 |
jurl --vision <url> | 1.3–1.9 s | $0.0002 |
jurl --find "…" <url> (73 images) | 2.2–2.9 s | $0.002 |
| JavaScript apps | +3–6 s | same |
Measured on 2026-10-04. Run any command with -t to see your own numbers.
jurl has no server and no account of its own. It talks to the model APIs directly with your keys:
--vision or --find, the images go to Cloudflare too. Keep that in mind for internal or private pages.brew upgrade jurl, or run the install script again.brew uninstall jurl, or delete ~/.local/bin/jurl. To remove everything, also delete ~/.config/jurl (keys) and ~/Library/Caches/jurl or ~/.cache/jurl (the browser).url ─▶ fetch (asks for markdown first) ─▶ split into blocks · links · images
└─ empty JavaScript app? ─▶ render in Lightpanda
│
one yes/no question per candidate
┌───────────┴───────────┐
▼ ▼
Jev reads text Clef looks at images
"is block 12 the point?" "does this show a cathedral?"
p = 0.97 p = 0.96
└───────────┬───────────┘
▼
rank · threshold · page order · print verbatim
text/markdown first; sites using Cloudflare's Markdown for Agents send it already converted. Otherwise jurl's own extractor drops navigation, footers, asides and scripts, and splits the rest into headings, paragraphs, list items, code, quotes and tables.xargs curl.--vision adds up the content classes and averages them with Jev's judgement of the page context: a portrait is content on Wikipedia and noise in an author box.--find, Clef decides alone. It sees the pixels and the alt text and caption.--vision fast:
PATH, jurl uses that. JURL_LIGHTPANDA points to a specific binary, and JURL_NO_DOWNLOAD stops the download. Lightpanda has no Windows build, so on Windows rendering is unavailable.cargo test # extraction: layout tables, lazy images, markdown, links, app-shell detection
cargo build --release && ./target/release/jurl -t <url>
| File | What's in it |
|---|---|
src/main.rs | Modes, chunking, hedging, output |
src/extract.rs | HTML and markdown → blocks, links, images |
src/decide.rs | Jev and Clef clients |
src/fetch.rs · src/lightpanda.rs | Fetching, rendering, the browser download |
src/setup.rs · src/config.rs | First-run key prompt, jurl init, key storage |
Releases are built by cargo-dist when a v* tag is pushed.
Issues and pull requests are welcome. Read CONTRIBUTING.md first; security problems go to SECURITY.md.
MIT or Apache-2.0, at your option. Lightpanda, which jurl downloads for JavaScript pages, is a separate program under AGPL-3.0.