Most tools that “read the web with AI” work the same way. They fetch the page, give it to a language model and let the model write the answer. Most of the time the answer is right. Now and then the model writes something the page never said, and nothing in the output tells you which time is which.
jurl works another way. Its models don’t write. They answer one kind of question, yes or no, with a probability, and jurl keeps what scores highest.
How a page gets read
- The page is cut into blocks. Headings, paragraphs, list items, tables, code. If the page is a JavaScript app, it’s rendered first in a headless browser. Menus, footers, cookie banners and forms are dropped before any model sees them.
- Every block gets the same question. With
-q "how do I install uv?", the question is whether the block helps answer that. Without a question, it’s whether the block is what a reader came for, rather than navigation or promos. All the blocks go in one request, so a page with 240 paragraphs is one or two calls, not 240. - The best blocks are printed in page order, word for word, under the heading of their section.
Links and images go the same way. With --links, each link is asked whether a reader would want to follow it. With --find "a cathedral", each image is looked at and asked whether it shows a cathedral, which is how jurl finds photos with no alt text.
What that changes
jurl can pick the wrong paragraph: a real one from the page, just not the best one. It can’t print a paragraph, a price or a URL that isn’t on the page, because nothing in it writes text.
So every result comes with its source. With --precise you get just the answer, still in the page’s words, and a link that opens the page with that sentence highlighted:
$ jurl --precise -q "what is the primary rate limit for authenticated users?" docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api
5,000 requests per hour
That matters most where nobody reads every result: a script filling a few thousand rows, an agent reading a hundred pages before it acts, an alert on a page that changes. Nobody checks them all, but any one of them can be checked in a click.
Where it stops
If the answer isn’t written on the page, jurl won’t work it out. A page that says “$8 a month” won’t give you the yearly price. When nothing on the page answers, jurl says so and exits with code 1. In a spreadsheet, an empty cell is better than a wrong one: the empty one at least looks empty.
The same rule runs through jurl’s tables: each value is quoted from a page, and when no page says it, the cell stays empty.