How to handle Webfinger for group discovery

Hi everyone, I’m a contributor to Lemmy, and have recently implemented Webfinger support for the project. That was already hard enough without any proper spec of how Webfinger is used by ActivityPub implementations. Now the problem is, Lemmy is mainly focused on groups (its a reddit alternative), but I am not aware of any other ActivityPub projects that support groups.

So my question is, what is the best way to handle Webfinger for groups? Webfinger URLs for user accounts look like this:

The easiest option that will most likely be supported by all existing projects is to use the same URL format for groups. But that will result in problems as soon as we also make users discoverable over webfinger, as users and groups with the same name will collide.

So I guess the next best option is to replace acct: with something else, like group:, like this:

Is there already some existing de-facto standard for this, or any other suggestion that would make compatiblity with other projects easier?

what would be the purpose of implementing webfinger for groups? what do you gain over, e.g., a URI?

As far as I know, webfinger is required to support eg discovery through the Mastodon search, so that something like ! can be turned into the actual URI that is used for ActivityPub. Sure we could always use the URI, but that would not be consistent with the functionality for discovering users, and also more complicated for end users.

1 Like

this was just merged into mainline Mastodon

thought I would pass this info here as it seems relevant

I actually saw this PR before, but it doesnt include anything about webfinger.

I’m planning to have groups in Smithereen, but thought they shouldn’t be any different from users on webfinger level, it’s just that the ActivityPub object that you’d fetch would be Group instead of Person :thinking:

It makes sense to do it as acct: because groups and users share the username namespace (for how I see it, anyway). You can’t have both a user and a group with the same username on the same instance.

It also makes sense to do it as group: because I’m going to store users and groups in separate tables in my database. This way I’ll know which one to select from, and whoever is sending the request can be sure that looking up a user won’t unexpectedly return a group and vice versa.


Well in Lemmy, users and groups are completely seperate, so you can have a group and a user with the same name of test. I also dont see anything in the activitypub spec that would prohibit this.

Can you post a link to your project? Search didnt bring anything up.

I haven’t published anything yet because it’s currently too far from being useful, and I haven’t even started implementing groups so most of this is theoretical. There is a live instance I mostly use for testing that successfully federates with the existing microblogging software.

I’ve been considering this question too for Drupal, where as well as users there can be groups through use of plugins like the Groups module.

Options I’ve come up with are:

  • Prevent name collisions. User and group names are globally unique. Probably not an option in many cases.
  • Allow groups and users to have the same name, but assign an alias in the case of collisions. For example if a user is created with the name “example” on a site where there is already an “example” group, the user is assigned the alias “example-1” which leads to the handle
  • For handles, use a convention where a string is appended to all group handles. A user “example” is while a group “example” is something like

option 3 is probably the most transparent and consistent way to handle things, i think? but also, if you want to avoid namespace collisions then it does make sense to have the URI handle this. Perhaps something like acct:group: as a subset of acct:?

the thing you will have to keep in mind is that mastodon et al expect acct:username@domain, but it is your decision whether you want to force this compatibility or not. if you do, then option 3 will work.

the thing you will have to keep in mind is that mastodon et al expect acct:username@domain , but it is your decision whether you want to force this compatibility or not

Yeah, good point. The workarounds I suggested above are going to cause more problems than they solve.

It seems to come down to the non-ActivityPub convention of a handle in the form, rather than the AP id URI. assumes that all actors are users, and so can be looked up (again, by convention, using Webfinger) using the acct schema, which as the acct draft makes explicit is:

a way to identify a user’s account at a service provider

And therefore limited, in most cases, to Person actors. (Sure, a Group could be a user on a site, but most often that’s not going to be the case.)

Yes, we could mess with the format, injecting a schema in there somewhere (, but (a) that’s not supported anywhere and (b) it pretty much defeats the original reason for the format and corresponding Webfinger workaround–that it’s considered intuitive.

So probably we’re left with:

  • For all actor types, the id URI works. Group actors use the id, not the format, for their handle. Webfinger doesn’t come into play.
  • For Person actor types only, and where the Person represents a user with an account on the site, is a secondary, alternate handle format, but one that isn’t guaranteed to be supported by all ActivityPub implementations.
1 Like

Another thing to consider: Webfinger in Mastodon is used primarily to allow mentions. Is your project going to use mentions of groups? If not, acct: lookup isn’t necessary – you can use the HTTPS URL, either transparently proxied/routed to the ID if the proper Accept header is provided, or you can still use Webfinger but with https: instead.

There’s nothing limiting acct: to Persons instead of Groups – what it represents in Mastodon’s expectations is a single shared namespace for actors according to a certain domain.


Still, I don’t understand why would any of you want to make group and user aliases be different namespaces and so allow there to be a user and a group with the same alias on the same instance. This would be very confusing UX.


@nutomic While testing things with lemmy, we verified that

To import a remote user we have lemmy.instance/u/nickname@gnusocial.instance. And that is working :slight_smile:

But importing a group with lemmy.instance/c/nickname@gnusocial.instance won’t. Looking at the logs we see that WebFinger is used to find groups via the acct: uri scheme. In GNU social we allow local users to have the same nickname as a local group (they are different namespaces). It has always been like this and we aren’t willing to introduce a breaking change. For us, and considering the RFC 7565 - The 'acct' URI Scheme, as @nedjo already elucidated, it only makes sense to support persons with the acct:.

Note that we don’t mind making groups and even different activitypub objects available in our webfinger endpoint, if that can be helpful, but that is as long as the resource is an URL or holds a new and more appropriate scheme (for groups that could, perhaps, be community:).

In GNU social, to fetch a remote group (or organisation), our users paste the Actor uri (or an alias) in the search box, and our ActivityPub plugin fetches it. We also have remote actions (OStatus connect), which is a button that opens a text input, allows you to write your home instance handle, and redirects to an endpoint with the URI of the group you were interested so that you can import it.

So the current state is:

  • Importing Lemmy groups to GNU social via the usual GNU social UI/UX works.
  • Importing a GNU social person via lemmy.instance/u/nickname@gnusocial.instance works.

But I can’t find an alternative way to lemmy.instance/c/WebFingerHandle that would allow me to import a GNU social group. Is there anything in Lemmy’s UI that will allow me to paste the URI of the gnu social group and import it?

For webfinger, we originally used acct: prefix for Person, and group: for Group. But we merged both under acct: in order to be compatible with Mastodon.

The proper way to fetch a remote actor is by pasting it in the search field. That works with the actor id as well, so webfinger is completely optional.

Oh, I did try the search field, but it states “No results.”.

The group:

	"type": "Group",
	"streams": [],
	"@context": "https:\/\/\/ns\/activitystreams",
	"id": "https:\/\/\/actor\/2",
	"inbox": "https:\/\/\/actor\/2\/inbox.json",
	"outbox": "https:\/\/\/actor\/2\/outbox.json",
	"following": "https:\/\/\/actor\/2\/subscriptions",
	"followers": "https:\/\/\/actor\/2\/subscribers",
	"liked": "https:\/\/\/actor\/2\/favourites",
	"preferredUsername": "hackers",
	"publicKey": {
		"id": "https:\/\/\/actor\/2#public-key",
		"owner": "https:\/\/\/actor\/2",
		"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvwd33xvZy4WWcGl7k6e+\ngl5I4O9sGRGOpfiCEYckHYorJ1NJjEHXWNY06NGBTZ7vI4kmD2GIxuYFij2XdetU\nZnFJG7JmiiibtZvwmqeVRoQmFUI6SsOslvwx0gXXlhSnGEWgzEvwUVhqvmDirP7L\nWMfmuci+QH+y+p7LnN0VFg3QmTQeafqW6bv\/zmdUtG0Boe0Ux7sw7yp4gViEojvy\npsyrHeKAxG0i60GQ3aeEvYCJVuBdd6c2gsSE3EyzT\/7gZtvydimhdpbbm42RepG7\npxFUKW3Op4Lq5LePDJ5OmxODF990wWw\/F\/zMIN+gdRf6BlYlA2BTOz+nI7E9HOn7\nywIDAQAB\n-----END PUBLIC KEY-----\n"
	"published": "2022-02-14T04:42:10+00:00",
	"updated": "2022-02-14T04:42:10+00:00",
	"url": "https:\/\/\/!hackers",
	"endpoints": {
		"sharedInbox": "https:\/\/\/inbox.json"

My search:

Does Lemmy maybe expect something additional in the group actor?

Oops, the name field is currently mandatory in Group, will make that optional.

1 Like

Tried out to set a name in the group settings and it was imported ^^

1 Like

So, this is very strange and maybe off topic but I guess the name is required thing comes from anything. It was just some days ago that I opened this issue 

@redaktor will handle it strictly AP conformant, based on the fact if Group is one of the types-Set, e.g.

{ "type": "Group" }
{ "type": ["Group", "Service"] }
{ "type": ["Group", "schema:Organization", "schema:NGO"] }