Bot

Someone saved a link to your page.

That is the whole reason this fetcher knocked. A person asked it to look for a title and preview image in your document — and here is everything about it that an access log won’t tell you.

The line in your log

bracemark-extractor/1.0 (+https://bracemark.com/extractor)

Bracemark is an end-to-end encrypted bookmark manager. When someone saves a link in the web app — or asks us to fill in ones they saved or imported earlier — the browser won’t let that page fetch yours, so this service fetches it instead: reads the title and the preview image, hands both back to the person’s own device, and forgets the address. It is the only server of ours that fetches a page at all: every other way of saving a link reads it on the person’s own device, from their own address.

It is a fetcher, not a crawler

There is no schedule and no index behind it. It never follows a link out of a page it fetched, never asks for a second page from your site on its own initiative, and never returns to see whether anything changed. Every address it asks for is one a person saved by hand or brought with them from another bookmark manager — nothing here discovers a page. One extraction attempt for one saved link makes one document request to you, plus one for a preview image if your document names one. A transient failure can be retried later. The person’s browser can’t read that image cross-origin any more than it could read your page — that’s why we need the second request.

There is a backlog, though, and it is theirs rather than ours. Links saved before previews were turned on, and anything brought in by an import, sit unfetched until their owner asks for them — so a request can arrive long after the save, and several can arrive together: a drain hands us addresses in batches — the cap on one request is in the table below — and we fetch a batch in parallel. Someone importing two hundred of your pages means one request for each page, close together; transient failures may be retried later. What decides the initial batch is the size of one person’s library, not a crawl or index of ours.

The person who asked keeps what comes back: it lives on their own devices from then on, encrypted, so saving the same address again doesn’t re-ask you for it.

It also only runs for people who turned it on. Fetching on someone’s behalf means seeing an address they chose to save, so it is an opt-in setting that is off until they enable it — the browser extension and the mobile apps read the page on the device instead, with no server of ours in it. The full account of that is in the privacy policy.

What it costs you

Every one of these is a hard cap in the code rather than a target, and each applies to every hop of every request.

Takes
a title · a preview image
Method
GET · no cookies, no credentials
Timeout
8 seconds per hop
Redirects
5 maximum
HTML read
first 1 MB, then cancelled
Images
10 MB ceiling · never resized
Per request
20 URLs at most
Rate limit
per calling IP address · a counter, not a log
JavaScript
not executed
Runs on
Cloudflare Workers

Because nothing on the page is executed, what it sees is the markup you served and nothing more: no stylesheet, script, or font is pulled in behind it, and a page that assembles its title in the browser yields nothing to find. The ceilings are ours as much as yours — this runs anonymously, so the caps are what keep it from being an open proxy pointed at your bandwidth. You can read every one of them, and the guard that re-checks each redirect before connecting to it, in github.com/stxapps/bracemark-monorepo — the service is AGPL-3.0, like the rest of Bracemark.

What it never does

Keep what it read
Nothing is buffered to disk, cached, indexed, or stored. What it finds goes straight back to the device that asked and the bytes are gone — there is no copy of your page at our end to leak, subpoena, or change our mind about.
Write down the address you saved
The whole reason this service is separate from the rest of Bracemark is that the URL it sees stays transient. Observability is counts, latency, and error rates — that address never reaches a log line. The one you connect FROM is a different thing and we do hold it, briefly: the rate limiter counts requests against it for a few seconds so that a single source can’t flood the service. It is never written down beside the URL, and the privacy policy inventories it.
Know who asked
Requests carry no account and no session. It cannot tell you which user saved your page, because it was never told.
Come back for the rest of your site
One request names one saved document. The fetcher has no queue of its own, never follows links it finds, and never schedules a revisit. It returns only when a person’s Bracemark client asks for a saved address again — for another pending link or a retry of an earlier attempt.
Feed a dataset or a model
Nothing fetched here trains anything, is resold, or is retained to be resold later. It is fetched for one person, delivered to their device, and encrypted there before it is written down anywhere.

It doesn’t read your robots.txt

Said plainly, because this is the page where you came looking for it. A robots directive won’t stop this fetcher, and we would rather disclose that than let you write a rule that quietly does nothing.

The reasoning, for what it is worth, is about who chose — not about how much gets read. A robots directive governs automated discovery: something deciding on its own what to visit next, at a cadence and a volume you never agreed to. Nothing here decides anything. One person put one address into their own library, one request went out because of that, and what came back went to their device and nowhere else. There is no queue behind it for a directive to shorten and no next page for it to keep us away from.

That is an argument, and one we could lose. It rests entirely on the request being one person’s and on there being exactly one of them. If this service ever fetches on its own initiative, or at a volume that a single save can’t account for, the argument is gone and this section gets rewritten rather than defended. Blocking by user agent works either way, which is why that is documented below.

How to turn it away

Match the user agent — every request carries bracemark-extractor in that header, and it is never spoofed as a browser — then answer with 403.

nginx

if ($http_user_agent ~* "bracemark-extractor") { return 403; }

Cloudflare WAF

(http.user_agent contains "bracemark-extractor")  →  Block

The status code you pick decides how long we keep trying. A 403 is retried on a widening backoff and then abandoned for good. A 404 or 410 settles it immediately, first time. A 429 or a 5xx reads as temporary, so it will come back — slowly, and at most once a day for that one link, but it will. The 403 in the rule above ends it; send a 410 instead if you would rather that happened on the first request than at the top of the ladder.

Don’t block it by address. It runs on Cloudflare Workers, so its requests leave from a shared pool that has nothing else to do with us, and banning those addresses costs you traffic you wanted while barely inconveniencing this.

What blocking does to the person who saved the link: they get your hostname as the title and no preview image. The link still works, they aren’t told why, and nothing else about your site is affected.

If it misbehaved

Write to abuse@bracemark.com. If it arrived more often than this page says it can, exceeded one of the caps above, or reached something it had no business reaching, that is a bug and we want it. The user-agent line, a few timestamps, and the paths are enough to find it at our end. A person reads that address, not an auto-responder.