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​