ActivityPub

One of the requests I (Evan) have heard often over the years about ActivityPub is to make publishing on the Fediverse as easy as publishing with RSS. To make an RSS feed for a person or a site, a publisher provides, dynamically or even statically, a single file, with a simple format, and makes it available over the Web. Other people’s feed reader software can download the feed and show the user either the full content of the site, or enough of a summary to get the user to click a link and read in their browser.

So… why can’t ActivityPub be like that? Make a feed, and let others read it if they want to?

The good news is, it can. ActivityPub defines an entire read-only structure for actors, content, and activities. Pushing content to other servers is entirely optional — you can just tell other servers that you don’t accept remote messages, and they won’t push them. The read-only interface to ActivityPub is rich and extensible — it covers content like text, images, video and audio, but also activities like liking, sharing, and replying. It’s not quite as simple as RSS — it requires a lot more, smaller files — but it’s pretty straightforward.

The bad news is that most widely-used ActivityPub software doesn’t recognize read-only ActivityPub feeds. Most ActivityPub servers expect to send messages to every actor, and to receive messages in reply. They don’t have internal facilities to check ActivityPub feeds regularly for new content and activities.

This isn’t just a technical issue; it’s also an adoption issue. If implementing ActivityPub requires all the infrastructure of our message-passing services — queues, signatures, filtering, fanout — it inhibits software developers and publishers from experimenting with the protocol. Implementing RSS can take a day or maybe a week of developer work. Implementing ActivityPub’s federation protocol can take months. Which one is going to be done in a hackday or a medium T-shirt-size sprint task, and which one is going on the back-back-back-backlog?

To make it easier to understand and support this proper subset of ActivityPub, I published FEP-b06c: ActivityPoll last summer. (“Poll” is in contrast to “publish” — emphasizing the read-only structure.) It’s a profile of ActivityPub, identifying parts of the ActivityPub spec that will work, or not, with a static, read-only ActivityPub publisher. It also includes new terms to easily identify a read-only ActivityPub actor, as well as a way to declare how often a feed is updated (very useful for limiting the load on both the reader and the server sides).

In order to test the profile, and identify shortfalls, I implemented a plugin for the static site generator (SSG) software, Jekyll. Using a static site generator keeps this process honest — there’s no temptation to add just a teensy bit of dynamic content generation; it has to be entirely static. If we can show interoperability with actors implemented with an SSG, we’ve shown that static ActivityPub publishing is truly possible.

The plugin is called jekyll-activitypub-static (there’s already a jekyll-activity-pub plugin, which uses off-site dynamic endpoints to implement the federation protocol, so this one emphasizes that it’s static). It’s in the rubygems.org repository, so you can just add the gem name to your Gemfile for your Jekyll site, and it should install correctly. The configuration is pretty straightforward, and has pretty reasonable fallbacks, but you can tweak it to get more specific features.

I’ve got an example actor on GitHub Pages at @evanp . You can search for it in Mastodon, and view the profile, but you can’t follow it directly. Other front ends can view it more directly — please tell me if yours can!

If you’ve got a Jekyll site, please try out jekyll-activitypub-static and let me know what you think. Fair warning — the Webfinger support depends on having your site deployed at the root of the domain. There are probably some ways to work around that — let me know if you find one! If you have changes or enhancements you think can be made to the plugin, let me know.

And if you’ve got a full-featured implementation of the ActivityPub federation protocol, please consider implementing a polling structure for static actors. FEP-b06c covers most of the caveats, but please feel free to leave a comment if you find another gotcha. I’ll be right in there with you — I’m going to implement it in onepage.pub and activitypub.bot.

Thanks to everyone who has commented on FEP-b06c, and to people who’ve tried and contributed to jekyll-activitypub-static. I look forward to more implementations!

Mallory and I (Evan) will both be at HOPE in New York tomorrow. Mallory is giving a talk on I-Stars: Protocols and Power on the main stage which looks awesome. I’ll be holding a workshop to help people Get on the Fediverse Already – setting up their Fediverse accounts for the first time. Since we’re both there, we want to have a meetup with the wider Fediverse community in New York!

So, we’re organizing a Fediverse Meetup at the Irish Exit inside the Moynihan Train Hall at Penn Station at 7PM. HOPE is just a block away at the New Yorker Hotel, so we think this is a good location. And who doesn’t love Penn Station?

We’ll grab a biggish table and put up a sign — you should be able to find us pretty easily. All Fediverse denizens and lovers of the Open Social Web are welcome. We will be around for a couple of hours at least — if you have a favourite evening talk at HOPE you don’t want to miss, please feel free to stop by. And watch the hashtag for news and pics.

On Friday, August 14, 2026 at the HOPE conference in New York City, we’ll be running a workshop to help new people join the Fediverse. This is an exciting first for us, and we’d love your help making it a great experience.

Here’s what we need:

Please reply to this post with ideas or contact info. This is going to be fun!

I (Evan) will be at the Wikimedia Hackathon 2026 in Milan, Italy this weekend (May 1-4). I’m especially interested in how we can connect Wikimedia projects and content to the Social Web using ActivityPub. I’ll be holding a session on the topic on Sunday May 3 at 9AM, but I’ll also be available for discussions throughout the weekend.

My hacking project plan is to make an ActivityPub object server for films. There are about 343,000 films in Wikidata, which compares pretty favourably with the 740,000 films in IMDB. There is a JSON-LD interface to Wikidata, but the types used don’t match up with ActivityPub types like Video. So, like places.pub, I’ll set up movies.pub to share an ActivityPub object for every Q-item for a movie, as well as a search endpoint to find films by name.

If I get ahead of the project and I’m not too jet-lagged, I’d like to add an ActivityPub API app to “check in” to a movie that you’re watching (and maybe give a little review). Similar to checkin.swf.pub with places!

If you’re at this weekend, please come say hi. I love talking about Wikimedia projects and the open social web.

I (Evan) will be giving talk at Fediforum 26-04 next week, April 28, 2026, on the exciting topic of faking your way through ActivityPub conversations. Here’s the description:

“One of the best bluffers in the field of distributed social networks gives you just enough knowledge about ActivityPub to sound smarter than everyone around you. In this talk, Evan will cover the essential architecture of ActivityPub, what works and what doesn’t, and what is coming up next for the standard. You’ll walk out of this talk with just enough knowledge to speak with confidence about anything at Fediforum.”

If you’ve ever wanted to know what ActivityPub is and how it works, please come along. I hope the event is fun and interesting. Bring questions!

The call for proposals is open for the COSCUP Fediverse track in Taipei, Taiwan. ActivityPub-related software, including server and client implementations, are great topics for the event.

COSCUP (“Conference for Open Source Coders, Users, and Promoters”) is the FOSDEM of East Asia. Run by the Open Source community in Taiwan, it brings together people excited about FOSS across the region.

For the first time, this year, members of the Korean ActivityPub developer community FediDev KR are joining up with FediLUG of Japan to program and run a Fediverse track at COSCUP. This has the potential to be a huge step forward for the Fediverse developer community. Although many major projects, like Fedify and Misskey, are created and promoted in East Asia, distance and language barriers make it hard for East Asian devs to participate in European and North American in-person events.

The Fediverse track is open to proposals about ActivityPub implementations, clients for ActivityPub platforms, ancillary services, libraries and toolkits. But also, as at FOSDEM, talks about the human aspects of Fediverse technology, like moderation, policy and governance, are welcome and encouraged. This event looks like it will cover as much interesting conceptual space as its twin at FOSDEM.

Hong Minhee, hongminhee@hollo.social, was one of the main speakers at FOSDEM’s Social Web devroom this year. Their talk about Fedify was important, but even more important was their effort to bridge the gap between Asia’s and Europe’s Fediverse development communities.

I (Evan) hope that COSCUP brings together many Asian developers, but I also hope that North American and European individuals and teams put in proposals as well. Knitting together these two important communities on the Fediverse requires effort from both sides. That’s why I’m applying to speak (about ActivityPub 1.1), and why I hope to see many familiar faces among the new ones in Taiwan.

tags.pub is a new service under development by the Social Web Foundation. It is a global hashtag server — it lets you follow a hashtag across the Fediverse. There’s lots of information on the tags.pub home page, and I (Evan) did a talk about tags.pub at FOSDEM 2026. This blog post answers some basics about tags.pub.

As part of my book “ActivityPub: Programming for the Social Web“, I created a coding example to show how to program for the ActivityPub API. ap is a command-line client, written in Python, for doing basic tasks with ActivityPub.

For example, you can log into a server using this command:

ap login yourname@yourserver.example

Once you’re logged in, you can follow someone:

ap follow other@different.example

Or, you could post some content:

ap create note --public "Hello, World"

This isn’t enough to have a real social networking experience, but I think it’s pretty useful for testing an ActivityPub API server, or automating some repetitive tasks.

I should note quickly here that not all ActivityPub servers support the ActivityPub API. It’s an under-utilized part of the ActivityPub standard. In particular, Mastodon, Threads, Flipboard, and other services don’t support the API. There’s a pretty good list of servers and clients that do support the API in this Codeberg issue.

Suffice it to say, unless you’re actively working with one of those platforms, or you are writing your own, you’re not going to get much use out of ap. It will probably give you an error message like “No OAuth endpoints found” if it can’t use the service.

Refreshing the project

I’ve never packaged ap for distribution; it was always supposed to be example code. But given the recent interest in the ActivityPub API, including the work going on in the ActivityPub API task force, I decided to get it into shape for installation by developers working on other apps. My friend Matthias Pfefferle of Automattic asked me about it when we were at FOSDEM this year, and I was embarrassed to see how difficult it was for him to use.

So, I’ve made two big upgrades to the package. The first was actually making it a package, and distributing it! I upgraded the package management framework to uv, which seems like a good bet for now, and pushing the application to PyPI, the Python Package Index. It’s visible at https://pypi.org/project/activitypub-cli/ now. (Note: different package name from the command name! The PyPI “ap” package name was taken a while ago.)

You can now install the application in one shot with this command on a computer that has Python on it:

pipx install activitypub-cli

You can test that the application installed correctly in your path by running the version command:

ap version

That should show the same version as is currently on the pypi.org page for the project.

The second change was implementing the current OAuth 2.0 profile best practices. I’ve upgraded the login flow so it tries a lot of different options for identifying itself to the server: CIMD, FEP d8c2, and Dynamic Client Registration. It tries to do them in preferential order; it uses permanent, global client identifiers before dynamic ones.

Help me test

I’m especially interested in testing this command-line client against other servers. If you’re developing an ActivityPub API server, please install the ap command and try it out against your (development!) server. Report a bug if it doesn’t work well, or send me a DM at @evanprodromou if it works OK. Given time, I think ap can be a useful first smoke test for ActivityPub API implementations.

Today the W3C standards organization announced a new working group to advance the ActivityPub and Activity Streams standards. The Social Web Foundation, as a W3C member organization, will be participating in the group. The working group’s goal is to release a backwards-compatible iteration of each specification in Q3 of 2026.

Activity Streams was released in 2017, and ActivityPub was released in early 2018. Since that time, the experience of hundreds of implementers and millions of users has shown places that the specifications are confusing or unclear, or missing features. Some problems have been documented with errata, but others require more work. The Next Version tag in the ActivityPub GitHub issue repository gives some good examples of topics to be considered. The new Social Web Working Group will provide revisions of these documents to make them easier to use for implementers.

ActivityPub is an actively used protocol with millions of users and billions of notes, images, video and audio files published. Standards work on ActivityPub will necessarily be evolutionary, not revolutionary, and will incorporate backwards compatibility. Developers can confidently keep working on ActivityPub today without worrying about breaking changes in the future.

The Social Web Working Group will work closely with the Social Web Community Group, the organization that has been stewarding ActivityPub and its extensions since 2018. The Community Group will remain the focal point for innovative developments extending ActivityPub into different areas like geosocial applications or threaded forums, while the Working Group will concentrate on the core documents.

One Community Group document that will be moving into the Working Group is LOLA, the live data portability spec that originated in the CG’s Data Portability Task Force. LOLA lets users move from one ActivityPub server to another while retaining all their social connections, their content, and their reactions. It’s a great improvement for data portability on the social web.

The Social Web Working Group will consist of representatives of W3C member organizations and invited experts from the standards and development community. The group will be chaired by Darius Kazemi, longtime contributor to the ActivityPub developer community. Meetings and proceedings will be public, and developers can review the work happening in the ActivityPub GitHub repository.

Thanks to everyone who’s done the work getting this charter to completion; especially Dmitri Zagidulin, the SocialCG chair who drove the charter editing and review process. Now, the work begins!

One of the project areas of the Social Web Foundation for the last year has been end-to-end encrypted messaging. ActivityPub, the standard protocol that powers the Social Web, has privacy controls, but they do not protect the content of messages from server operators. Encrypted messaging has become a common feature on many social networks since ActivityPub was created, and its lack has inhibited Social Web adoption and public trust in the network.

ActivityPub is extensible, though. As part of our E2EE program, Mallory, Tom and I adapted the Messaging Layer Security (MLS) standard as an extension of ActivityPub to make the MLS over ActivityPub specification. The protocol fits the great MLS E2EE system onto the ActivityPub API and federation protocol.

But a protocol specification is not enough; it must be implemented. That’s why we’re so happy to announce that the Sovereign Tech Fund has commissioned work with the Social Web Foundation to coordinate two new interoperable implementations of MLS over ActivityPub. This investment by the Sovereign Tech Fund will help move the Fediverse towards more privacy for social web users, no matter what server they use.

We decided to partner with two different projects in order to make sure that we’re making an open standard that can work between implementations. With two implementers, we’ll need to communicate clearly about architectural and implementation decisions, and make sure that those decisions end up in the final version of the spec — not in a TODO comment in the source code of a single project.

The first project is Emissary, the great social web application platform behind projects like Atlas and Bandwagon. Ben Pate, Emissary founder, says, “The Emissary Project is deeply committed to the Fediverse, where we are building a free and trustworthy Internet for all 8 billion humans. Delivering on that promise, Emissary is excited to team up with the Social Web Foundation to bring End-to-End-Encryption (E2EE) to the Fediverse. We are eternally grateful for the SWF’s leadership and support, without which this project could not have happened.  Our work is already underway, and in 2026 anyone will be able to build E2EE applications on the Emissary platform.”

The second project is Bonfire. Bonfire is a modular framework for building federated apps, with its first app (Bonfire Social) offering a social networking experience enhanced with tools for privacy, trust, and collaboration (such as circles and boundaries).

The maintainers of Bonfire, Ivan Minutillo and Mayel de Borniol, said: “We think that end-to-end encryption should simply be the default for any private communication online. Working with the Social Web Foundation to bring E2EE to ActivityPub marks a crucial step in fostering privacy and trust, and especially in enabling the fediverse to become a safe space for activists and communities to organise, coordinate, and collaborate meaningfully. By making secure, user-friendly messaging a core part of the fediverse, we’re helping lay the groundwork for decentralised networks where people can go beyond talking in the mythical ‘global town square’ and actually organise and accomplish things together.”

This work will happen best if the Fediverse community tracks it closely. We’ll be making updates here on the SWF blog as progress continues. Developers and active users may also be interested in the ActivityPub E2EE Messaging Task Force at the W3C, where the specification is being developed into a report for the Social Web Community group. Finally, we’ll be using the #JustBetweenUs hashtag to share progress and ideas, so you can follow it to see what’s been happening.