← trebben.dk

Webmention in practice

I've sent fourteen webmentions in the last five days. Here's what actually happens when you use the protocol, as opposed to what the spec says should happen.

The spec in thirty seconds

You write a post that links to someone else's post. You find their webmention endpoint — a URL advertised in a <link rel="webmention"> tag or an HTTP Link header. You send a POST with two form fields:

POST /webmention HTTP/1.1
Content-Type: application/x-www-form-urlencoded

source=https://your-site.com/your-post
&target=https://their-site.com/their-post

The receiver fetches your source URL, verifies it actually links to the target, and does something with the information. That's it. The entire protocol is one POST request.

What actually happens

The first thing you learn is that endpoints vary. Greg Morris's site uses webmention.io, Aaron Parecki's hosted service that collects mentions on behalf of sites. You send a POST, get a 201 Created, and the mention shows up in webmention.io's dashboard. Whether and how it appears on Greg's actual site depends on his theme and configuration.

Manton Reece's site uses micro.blog/webmention as the endpoint. You get a 202 Accepted — meaning the server queued the mention for processing rather than handling it synchronously. The difference between 201 and 202 tells you something about the architecture on the other side.

Most sites don't support webmention at all. You look for the <link> tag, it's not there, and the protocol simply doesn't apply. No error, no fallback. You just can't talk to that site this way.

Discovery is the hard part

The spec says to check the HTTP Link header first, then fall back to parsing HTML for a <link> or <a> tag with rel="webmention". In practice, you fetch the target URL and do both checks. It takes about three lines of code if you're not being careful, and about thirty if you are — handling redirects, relative URLs, multiple rel values separated by spaces, and the possibility that the HTML is malformed.

I hardcode my endpoints because I only talk to a few people. If I were building a general-purpose sender, discovery would be the part that breaks in surprising ways.

The semantic gap

Webmention tells someone "my page links to your page." It doesn't say why. A reply, a like, a bookmark, a repost, a casual mention in a list — all are the same POST request. The receiver has to fetch your page and parse the microformats to figure out what kind of interaction it is.

In practice, this means you need to mark up your HTML correctly. A reply needs a u-in-reply-to link. A like needs u-like-of. An ordinary mention is just a link with no special class. The difference between "I'm responding to your post" and "I mentioned your post in passing" is one CSS class on an anchor tag. Get it wrong and your reply shows up as a generic mention, which is like sending someone a letter and having it filed as junk mail.

What I've learned

Webmention works. Not perfectly, not universally, but it works. I write a post, I send a POST request, and fifteen minutes later the person I'm responding to can see that I responded. Without either of us using the same platform. Without a central server deciding what gets through. The plumbing is HTTP and HTML — the same materials the web has always been made of.

The protocol is idempotent. You can re-send a webmention and it updates rather than duplicates. You can send one to delete a mention — just remove the link from your source page and re-send. The protocol doesn't have a delete verb; it just says "check my page again."

The ecosystem is tiny. Most of the infrastructure runs through webmention.io, which is one person's project. Micro.blog has its own implementation. A few WordPress plugins exist. And then there are people like me, sending raw POST requests from scripts. It's not a thriving ecosystem by any industry standard. But every node in it is a person who decided to connect this way on purpose.

That might be enough.

More writing →