Skip to main content

Testing Tools

Tools and resources for testing ActivityPub implementations.

Online Tools

ActivityPub Academy

Test server for development.

PropertyValue
Websiteactivitypub.academy
PurposeInteractive testing
FeaturesTest actors, activities

Webfinger.net

WebFinger lookup tool.

PropertyValue
Websitewebfinger.net
PurposeTest WebFinger
UsageEnter handle, see response

JSON-LD Playground

Validate JSON-LD documents.

PropertyValue
Websitejson-ld.org/playground
PurposeExpand/compact JSON-LD
FeaturesVisualize document

Command-Line Testing

curl for ActivityPub

Fetch an actor:

curl -H "Accept: application/activity+json" \
https://mastodon.social/users/Gargron

Test WebFinger:

curl "https://mastodon.social/.well-known/webfinger?resource=acct:Gargron@mastodon.social"

Fetch NodeInfo:

curl https://mastodon.social/.well-known/nodeinfo

httpie (alternative to curl)

# Install: pip install httpie
http GET https://mastodon.social/users/Gargron \
Accept:application/activity+json

Local Development

Test Servers

ActorServer - Minimal test server:

# Python example
python -m http.server 8000
# Serve static actor JSON

ngrok - Expose local server:

ngrok http 3000
# Get public URL for testing federation

Local Mastodon

For integration testing:

git clone https://github.com/mastodon/mastodon
cd mastodon
docker-compose up
# Access at localhost:3000

Test Cases

Minimum Viable Actor

Test your actor endpoint returns:

{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Person",
"id": "https://example.com/users/test",
"preferredUsername": "test",
"inbox": "https://example.com/users/test/inbox",
"outbox": "https://example.com/users/test/outbox",
"publicKey": {
"id": "https://example.com/users/test#main-key",
"owner": "https://example.com/users/test",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----..."
}
}

WebFinger Response

Test /.well-known/webfinger?resource=acct:test@example.com:

{
"subject": "acct:test@example.com",
"links": [
{
"rel": "self",
"type": "application/activity+json",
"href": "https://example.com/users/test"
}
]
}

HTTP Signature Validation

Use existing servers to test signing:

  1. Create test activity
  2. Sign with your implementation
  3. POST to real inbox (test instance)
  4. Check for 202 Accepted

Integration Testing

Test Matrix

TestDescriptionExpected
Actor fetchGET /users/testValid actor JSON
WebFingerGET /.well-known/webfingerLinks array
NodeInfoGET /.well-known/nodeinfoValid nodeinfo
Inbox POSTPOST activity202 Accepted
FollowSend FollowAccept received
CreateSend Create NoteNote appears

Automated Testing Script

import requests

BASE_URL = "https://your-server.example"

def test_actor():
resp = requests.get(
f"{BASE_URL}/users/test",
headers={"Accept": "application/activity+json"}
)
assert resp.status_code == 200
data = resp.json()
assert data["type"] == "Person"
assert "inbox" in data
print("✓ Actor endpoint")

def test_webfinger():
resp = requests.get(
f"{BASE_URL}/.well-known/webfinger",
params={"resource": "acct:test@your-server.example"}
)
assert resp.status_code == 200
data = resp.json()
assert "links" in data
print("✓ WebFinger endpoint")

if __name__ == "__main__":
test_actor()
test_webfinger()
print("All tests passed!")

Debugging

Common Issues

SymptomLikely CauseSolution
401 on inboxBad signatureCheck signing
404 on actorWrong AcceptAdd header
No federationBlocked IPCheck firewall
Signature invalidClock skewSync NTP

Logging

Enable verbose logging:

// Node.js example
app.use((req, res, next) => {
console.log({
method: req.method,
path: req.path,
headers: req.headers,
body: req.body
});
next();
});

Test Accounts

Public Test Instances

  • activitypub.academy - Test server
  • Your own test instance - Recommended

Creating Test Accounts

  1. Set up local Mastodon
  2. Create test users
  3. Follow/interact with your server
  4. Check delivery and responses

See Also