How to make profiles/activities on my instance available for users on other instances


I am totally new to ActivityPub and related protocols (ActivityStream, WebFinger, JSON-LD, etc). I have heard of Mastodon for years and I somehow independently reinvented the idea of federated network back in 2018 (or 2017), but not before 2023-01-13 did I create a Mastodon account or look into the specifications of the underlying protocol.

Also, not until I got scared away by the dependency hell of Mastodon did I really want to learn the protocol in the hope of making my own implementation.

BTW personally I would prefer XML over JSON if I were to design a protocol for similar purposes over some representation layer protocol, but that is another topic…

What I am doing

I am developing ApubNode, a CLI tool for generating static websites which are supposed to partially support ActivityPub — to publish activities in HTML and JSON-LD like other ActivityPub-compatible servers, but interaction features (e.g. reply, comment, like, direct message) are to be omitted. Please forgive the inaccurate impression of favoring Nodejs being implied by the name (although it does involve Nodejs components); ‘Node’ means ‘static website instance’.

An online demo has been deployed on Cloudflare Pages (very reasonable for a static lover), available at For debugging purposes, all JSON files are visibly linked from anchors. At the profile page, you may see 3 types of anchors pointing to .json URLs (Person, Outbox, and Action). I believe that these JSON files should be valid.

With Cloudflare Pages Functions, it can serve the WebFinger lookup endpoint for user profiles. The JSON looks similar to those served by Mastodon, and I think this part should be valid, too.

What is confusing me

For what have been implemented, theoretically speaking, a full-feature subscriber (peer server) should be able to find my activities through the chain of short handle → WebFinger lookup → JSON URL for Outbox index → JSON URL for Outbox paged. The paging feature is not yet implemented, serving all Actions at once in one file, and I believe that this is not going to cause problems.

However, I have found no way to see my self-hosted profile in the eyes of any other peer server. Mastodon instances, e.g. (the instance which I first started playing with) cannot load my profile with a simple short handle. This is open for different interpretations. I could imagine that some part of my code was wrong, or Mastodon has hidden mechanisms or features about ‘exotic profiles’ which I was unaware of (e.g. limits with retrieval).

It will be good if there is any server (source code or online instance) that truthfully does the handling and parsing of exotic profile. so that I may know how other people would see my profile from their existing ActivityPub-compatible servers.

How you could help me

At this moment, I cannot tell whether there is any bug with in code or is there a limitation in Mastodon. A testing suite should be good, but the old test suite, whose public deployment was discontinued, is still linked on ActivityPub website homepage. Also, I have gathered that the attempts on developing a new test suite was not really fast or successful. So perhaps some human inspection on my artifacts (JSON, etc) and code will be helpful.

The online demo instance is also available on GitHub; it might be more convenient to read artifacts and code there.


I just had a quick look. You have an ‘actor document’ at

and it appears to be returned in ActivityPub fetches,

But its ‘id’ is

which only returns an HTML page.

Fetching the ‘id’ with an Accept header of

application/ld+json; profile=""

Should return the actor document. So change the id to

You can put the URL of the webpage in a ‘url’ element.

Many of us leave off the ‘.json’ completely and just use the Accept header to decide whether to return a json document or an html page for a given URL. This might be a bit more difficult with a static site and isn’t strictly necessary, but I’ll mention it because that’s how most of the fediverse works.

It is actually forbidden to serve webfinger over http. You must serve it via https, but doing so I get a 500 error.

Please use https everywhere. I believe this also is a fediverse requirement.


Thank you. The information you offered was really helpful.

I have fixed the problems you mentioned, and others I noticed in the process.

I would like to clarify that I did write ‘https’ in some testing tool, and the ‘http’ here was a copy-paste mistake.

However, at this moment,, the instance I have been playing with, still cannot load my remote profile in its webpage. The problem of testing profile availability remains…

1 Like

Try changing the webfinger rel=“self” link to type “application/activity+json” instead of “application/ld+json”.

From the Mastodon documentation:

You can parse this JSON response to find a link with your desired type. For ActivityPub id , we are interested in finding application/activity+json specifically.

WebFinger - Mastodon documentation (

EDIT: Looking at the Mastodon source code, it looks like you can also use :

'application/ld+json; profile=""'

Also, the webfinger rel=“self” link for the outbox is going to confuse Mastodon. I recommend removing it since the outbox information is in Person.json.