Skip to main content
ActivityPub

ActivityPub

Active

ActivityPub is a W3C Recommendation (2018) for decentralized social networking. It defines a server-to-server federation protocol and a client-to-server API, both using ActivityStreams 2.0 JSON-LD as the data format. Actors (users, groups, services) have inbox and outbox endpoints. Mastodon, PeerTube, Pixelfed, Lemmy, and 10,000+ servers form the Fediverse – a federated social network of 10+ million users all interoperating via ActivityPub.

ActivityPubFediverseMastodonW3CFederationActivityStreams2018
Actor Types

In one line

ActivityPub (W3C Recommendation, January 2018) is the federation protocol powering the Fediverse. Every actor has an inbox (receives Activities) and an outbox (publishes Activities). Server-to-server federation: when Alice on mastodon.social follows Bob on fosstodon.org, mastodon.social POSTs a Follow activity to Bob's inbox on fosstodon.org. Activities use ActivityStreams 2.0 JSON-LD. Actor discovery uses WebFinger (RFC 7033). Content is end-to-end signed using HTTP Signatures.

Quick Reference

FieldSizeDescription
ActorJSON-LD objectPerson, Group, Organization, Application, or Service. Every actor has an id (HTTPS URL), inbox, outbox, followers, following collections.
InboxPOST endpointHTTPS URL where other servers POST activities. The server validates the activity, deduplicates, and notifies local users. Authenticated via HTTP Signatures.
OutboxGET/POST endpointContains all public activities by the actor as an OrderedCollection. GET returns the actor's public timeline. POST creates new activities (C2S API).
Activity types16 core typesCreate, Update, Delete, Follow, Accept, Reject, Like, Announce (boost/repost), Block, Undo, Add, Remove, Move, Flag, Ignore, Join. Each wraps an Object.
Object typesNote, Article, ...Note (Mastodon post), Article (blog post), Video (PeerTube), Image (Pixelfed), Question (polls), Audio, Event, Place. Wrapped inside Activities.
WebFingerRFC 7033Actor discovery: GET /.well-known/webfinger?resource=acct:user@domain returns the actor's profile URL. How @user@domain lookups work across servers.
HTTP SignaturesDraft specAll S2S federation requests include an HTTP Signature header signing the request body with the actor's RSA private key. Receivers verify against the actor's public key from the actor document.
JSON-LD context@contextEvery ActivityPub object must include "@context": "https://www.w3.org/ns/activitystreams". Servers may add extension contexts for Mastodon-specific fields.

Key Characteristics

Federated delivery

When an actor publishes a post, the server looks up followers' inbox URLs across all servers and POSTs the activity to each. No central server involved.

HTTP Signatures

All server-to-server requests are signed. The receiving server fetches the sender's public key from the actor document and verifies the signature, preventing spoofing.

No end-to-end encryption

ActivityPub transmits content in cleartext to all participant servers. The server admin can read all federated messages. For E2E encryption, see Matrix or XMPP.

Pull vs push

S2S federation is push-based: senders POST to receivers' inboxes. However, fetching old outbox content is pull-based (GET the outbox collection). Both patterns are part of the spec.

Message Format

Request
http
// Actor document (fetched via WebFinger discovery)
GET https://mastodon.social/users/alice HTTP/1.1
Accept: application/activity+json

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Person",
  "id": "https://mastodon.social/users/alice",
  "inbox": "https://mastodon.social/users/alice/inbox",
  "outbox": "https://mastodon.social/users/alice/outbox",
  "followers": "https://mastodon.social/users/alice/followers",
  "following": "https://mastodon.social/users/alice/following",
  "preferredUsername": "alice",
  "publicKey": {
    "id": "https://mastodon.social/users/alice#main-key",
    "owner": "https://mastodon.social/users/alice",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----
..."
  }
}
Response
http
// S2S: alice follows bob (fosstodon → mastodon.social)
POST https://mastodon.social/users/alice/inbox HTTP/1.1
Content-Type: application/activity+json
Signature: keyId="...",algorithm="rsa-sha256",headers="...",signature="..."

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Follow",
  "id": "https://fosstodon.org/users/bob/follows/123",
  "actor": "https://fosstodon.org/users/bob",
  "object": "https://mastodon.social/users/alice"
}

// mastodon.social accepts and notifies alice:
// POST https://fosstodon.org/users/bob/inbox
{
  "type": "Accept",
  "actor": "https://mastodon.social/users/alice",
  "object": "https://fosstodon.org/users/bob/follows/123"
}

Implementations

linuxsince Mastodon (Ruby), Pleroma/Akkoma (Elixir), PeerTube (Node.js/TypeScript), Misskey/Calckey (Node.js), Lemmy (Rust), Pixelfed (PHP)available
macossince Same server implementations. Ivory (iOS/macOS Mastodon client).available
windowssince All server implementations run on Windows. Windows Mastodon clients available.available
iossince Ivory, Ice Cubes, Toot! (Mastodon iOS clients)available
androidsince Tusky, Moshidon, Megalodon (Mastodon Android clients)available