Mastodon is a federated micro-blogging service. “Federated” means that there are many servers, each with their own rules, unlike Facebook, Google+ or Twitter. “Micro-blogging” means that you can post status updates up to 500 characters long.

I wrote mastodon-backup so that people can download their own toots, favorites and media attachments.

I also wrote bitlbee-mastodon. This plugin allows Bitblee to communicate with Mastodon instances. Bitlbee is an IRC server connecting to various other text messaging services. You run Bitlbee and connect to it using an IRC client, then configure Bitblee to connect to other services, such as a Mastodon instance where you already have an account. The benefit is that you can now use any IRC client you want to connect to Mastodon.

If you’re new, I recommend this post: How to Mastodon.

2018-06-15 No Twitter, No Facebook

Tired of ads in your feed?

Tired of some algorithm picking some posts to show and others to hide?

Tired them selling your data to everybody One their dog?

Join Mastodon!

The woman who taught internet strangers to actually care for one another. «Echo represents a lost vision of social media. If Facebook, Instagram and Twitter are big social, then Echo is small social. It’s also just what we need right now. […] Perhaps big social was never the right outcome for this wild experiment we call the internet. Perhaps we’d be happier with constellations of smaller, regional, and interest-specific communities; communities whose stakeholders are the users themselves, and whose moderators and decision-makers aren’t rendered opaque through distance and centralized authority. Perhaps social life doesn’t scale. Perhaps the future looks very much like the past. More like Echo.»

Or this, same article: «Today the role of moderators has changed. Rather than deputized members of our own community, they are a precarious workforce on the front lines of digital trauma. The raw feed of flagged Facebook content is unimaginable to the average user: a parade of violence, pornography, and hate speech.»


Add Comment

2018-06-14 Wrote a Bot

I wrote a Mastodon bot: @textmapper. It posts a Text Mapper map once a day.

It was surprisingly easy to do! I’m still confused by how easy it was. I was expecting some bugs. It... just worked!? I had great libraries to work with:, CairoSVG, and all the other things I used.

I’m also using the Software Wiki to keep track of ideas.


Add Comment

2018-05-12 Mastodon OAuth2 Issues

I signed up for a new instance and noticed that Mastodon Archive doesn’t allow me to log in using OAuth2. What’s going on? Let’s look at the API again.

Register the application:

curl -X POST -d "client_name=mastodon-archive&redirect_uris=urn:ietf:wg:oauth:2.0:oob&scopes=read" -Ss

This gives me a JSON containing client_id and client_secret. Store these as environment variables of the same name.

Store the password in an environment variable, too.

export client_id=...
export client_secret=...
export password=...

Login to get the access token:

curl -X POST -d "client_id=$client_id&client_secret=$client_secret&grant_type=password&$password" -Ss

Store it in an environment variable, of course.

export access=token=...

Test it:

curl --header "Authorization: Bearer $access_token" -sS

This seems to work even though it doesn’t work for Mastodon Archive!

Let’s create the necessary files, manually:

echo $client_id >
echo $client_secret >>
echo $access_token >

And test it:

$ mastodon-archive archive
Get user info
Get statuses (this may take a while)
Get favourites (this may take a while)
Skipping mentions
Skipping followers
Saving 33 statuses, 13 favourites, 0 mentions, and 0 followers

Thus, we now know that the problem is the app registration and obtaining the access token. Everything else works as expected.


Comments on 2018-05-12 Mastodon OAuth2 Issues

Debugging what does... Here is what my code does, essentially:

print("Registering app")
    api_base_url = url,
    to_file = client_secret)

print("Log in")
mastodon = Mastodon(
    client_id = client_secret,
    api_base_url = url,
    debug_requests = True)

url = mastodon.auth_request_url(
    client_id = client_secret,

print("Visit the following URL and authorize the app:")

print("Then paste the access token here:")
token = sys.stdin.readline().rstrip()

    username = username,
    code = token,
    to_file = user_secret,

And I get the error in the last statement.

Registering app
Log in
Mastodon: Request to endpoint "/api/v1/instance/" using method "GET".
Parameters: {}
Headers: None
Files: {}
Mastodon: Response received with code 200.
response headers: {...}
Response text content: {...}
Visit the following URL and authorize the app:
Then paste the access token here:
Mastodon: Request to endpoint "/oauth/token" using method "POST".
Parameters: {'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob', 'code': '...033d', 'grant_type': 'authorization_code', 'client_id': '...8aba', 'client_secret': '...b138', 'scope': 'read'}
Headers: None
Files: {}
Mastodon: Response received with code 401.
response headers: {... 'WWW-Authenticate': 'Bearer realm="Doorkeeper", error="invalid_grant", error_description="The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."' ...}
Response text content: {"error":"invalid_grant","error_description":"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."}

I started wondering: is this because of the scope parameter? I was missing the scope parameter in my call to create_app. I made that change but saw no difference.

I then thought perhaps the problem is the missing redirect_uris in auth_request_url and redirect_uri in log_in. I added them both but saw no difference.

I then thought perhaps something about scopes was wrong so I removed scopes, redirect_uris and redirect_uri from the various calls but saw no difference.

Sadly, the documentation and the Doorkeeper documentation it refers to is very sparse indeed. doesn’t tell me how to really do OAuth and Doorkeeper only tells me how to do it with a password (Resource Owner Password Credentials) and not how to use Client Credentials.

It is all quite frustrating.

And most disturbing of all: it continues to work for but doesn’t work for any of the other instances I have tried, e.g.

As I said, it is all quite frustrating.

As expected, switching the entire thing to password credentials “works”:

mastodon = Mastodon(
    client_id = client_secret,
    api_base_url = url)

print("We need your credentials just this once to log in.")
sys.stdout.write("Email: ")
email = sys.stdin.readline().rstrip()
sys.stdout.write("Password: ")
password = sys.stdin.readline().rstrip()

    username = email,
    password = password,
    to_file = user_secret,

The result:

$ mastodon-archive login
We need your credentials just this once to log in.
Password: *secret*
Get user info
Login OK

The word of the day is “frustrating”.

– Alex Schroeder 2018-05-13 19:23 UTC

Add Comment

2018-04-13 Social Media Goals

More Mastodon thoughts...

Initial tests with automatic anti-lurker measures: of my 513 followers 289 haven’t mentioned me in the last 12 weeks (same number if considering all the mentions, ever). That would be a strangely big list of people to block, if that was my strategy to block bots and spyware. But isn’t interaction what I’m here for? I feel like radio blocking listeners who never call in. Or should I feel like hanging up the phone when the other side never says a word? That’s creepy, too.

The social sniffer is what I’m concerned about. I guess I just want to make that harder. Then again, sniffers can just slurp the public timeline and get all the data, right... 😭

On Google+ and Facebook, I blocked all the accounts that looked like spammers and leeches to me. They had to have something, anything on their profile to indicate that they were interested in communicating with me, or a common interest. Just a signal. Anything.

I guess one other thing I could try is unfollow anybody who isn’t following me? I realize that such a mass unfollow and blocking tool is not for everybody but I keep wondering what kind of social media I’d actually want to see and I keep thinking I want to connect with people, and have conversations. If we’re not having conversations, perhaps we should just read each other’s blogs. Or perhaps I’m demonstrating to myself how conflicted I am about the entire notion of social media.

I just imagine sitting in a room full of people. I sometimes say a thing. Some people wink. Some people wave. Some people say something back. And some just sit there and listen. They’re eyes looking at me, at the people reacting, back at me. They never blink. It’s creepy as hell. What are they doing in the same room as I am. I want to invite them into the conversation but I don’t need them just sitting there, listening in.

Clearly some people have something to say to a lot of followers. They act like multiplicators. They can have a beneficial effect, like teachers. People learn by following them. Or they can be influencers, adsters, fakesters, propagandists, sniffers, marketeers, profilers, secret service, all sorts of unsavoury jobs. But if you follow somebody like you follow a blogger, clearly an intentional one-way communication, then that’s cool. But I think that’s not what I want.

Maybe I want a slow moving, asynchronous chat room.

I’ll think about this some more, for sure. I think writing the code and looking at what it would actually do, seeing those ratios, perhaps that’ll help me make up my mind. What is it that I want from Mastodon?


Comments on 2018-04-13 Social Media Goals

I think the shear amount of stuff that one can read is so big, that it’s really difficult to stop for a moment and talk back, instead of moving to your next favourite corner of the Internet. As for me, I often don’t know what to say!

I like Twitter for the ease of interaction. I like blogs for solid bodies of communication, with links, history, pictures... I don’t love G+, but all the interesting folks are there!

– Enzo 2018-04-17 16:17 UTC

Yeah, the big exodus from Blogs to G+ still hurts! 😅

– Alex Schroeder 2018-04-18 13:56 UTC

Add Comment

2018-01-31 Mastodon CSS

Here’s an interesting fix to the Mastodon CSS: “now the columns in the Mastodon web UI don’t scroll independently anymore, and it’s a huge improvement for keyboard-control.”

@-moz-document domain( {
    .column:nth-of-type(2) { width: 600px !important; }
    .columns-area { x-overflow: none !important; }


I have no idea how I did this, but I was poking around in the inspector and deleted a CSS rule, and now the columns in the Mastodon web UI don't scroll independently anymore, and it's a *huge* improvement for keyboard-control. (The focus model for multi-columns with independent scrolling is a huge headache I could never figure out satisfactorily.)

So the trick is to select the "columns-area" div and disable the "overflow-x: auto" rule; boom. Nicer scrolling for all!

The main thing I like about this is that it makes expanded column width more usable as well:

@-moz-document domain( {
.column:nth-of-type(2) { width: 600px !important; }
.columns-area { x-overflow: none !important; }

The default Mastodon column width of ~25 characters is just Bad, and I'm glad it's within my power to fix it myself.


Add Comment

2018-01-20 Mastodon Archive 0.0.5

I made a new Mastodon Archive release.

Changes from 0.0.4 to 0.0.5:

  • use a User-Agent of Mastodon-Archive/0.0 when downloading media files
  • warn if toot expiration is going to take a long time due to rate limiting
  • report on favourites
  • report default to a 12 week time window with an option to change it
  • report default to top 10 tags with an option to change it
  • add an option to include boosted toots in your hashtag report
  • when providing all as your user, then the subcommand will run for every archive in the current directory


Add Comment

2018-01-13 No Google Plus

A while ago I discovered Mastodon and loved it. I didn’t worry too much about being tracked. Everything and everybody was new. Posts were shorter. And I basically switched. I’m no longer a big Google+ poster.

I had joined Google+ because of all the other RPG people. The Old School Renaissance (OSR) folks had all collectively moved their talking from blogs to Google+, I felt. But in recent months I have often felt that many posts on Google+ were about politics, and they were getting me down. The orange pumpkin US president also didn’t help (Trump, in case I come back to this blog post many years later and have forgotten who it was). I wanted to read about politics but it was getting me down. I wanted to read about role-laying games but that was getting me down, too!

It’s hard to explain. Some posts were too long. Huge! Others were just linkspam, sometimes nothing but a link, or sometimes a very short sentence or two, plus a link, sometimes posted in multiple Google Communities. Even though that didn’t affect me much, it still made me a little angry. It’s stupid, I know.

Mastodon has a 500 character limit and no markup. Those limitations are stupid, too. But strangely, I feel more comfortable in this environment. And I noticed something else: I am quite comfortable posting about code and programming, something I had mostly kept out of my Google+.

Perhaps that’s because the RPG instance I am on,, isn’t too interesting as far as the OSR goes. And so I did not post too much over there.

I thought the change would be hard. But it turns out it isn’t.


Add Comment

2017-12-15 Including Mastodon Comments

Steve Ivy suggested pulling in replies to a Mastodon status referring to a blog post, and suggested using the regular API for it, because displaying a status and its context doesn’t require authorization. Interesting idea!

But then again: Am I no longer going to expire these toots?

shower thought: wondering if I could automate posting links to my blog posts on mastodon, then pull in replies and boosts via *javascript* (like masto-discus)


Add Comment

2017-11-29 What to do with Mastodon

On Dice Camp, Meguey Baker asked:

A follow up question: what are we doing now that we’re here? Let us gather for a purpose beyond “talk about stuff and things!” What gives us meaning, individually and collectively? There is a massive massive massive flood of “content” in the world; we are super saturated with it. Lots of us make it. Im not saying anyone stop, I’m saying what could we make together if we had a plan?

I think instances which are small and focused on a project could exist for a distributed team. But that sounds a lot like work. But that’s one thing that people could do: work.

I know a thing I don’t want to do: promoting, and reading promotions. I am saturated with content, and products.

But there are models for the things in between: book reading clubs (not buying books); social clubs (talking about thing but aiming at an improvement of self and society along some axis).

Personally, I’m mostly interested in what differentiates a salon in Paris a few decades ago from a public space. Curation of members, curation of topics, invitation of guests, these are the obvious outer limits. But there must have been expectation management as well. What did members hope to gain through their membership? Entertainment? Advancement? How much bowing was expected? How much free labor? I understand so little about this.

Also related: Royal Society of London for Improving Natural Knowledge. Could this be a Society for Improving the Art of Role-Playing Games? All games? Pushing envelopes? Feedback sessions? Criticism? I don’t want to deny the negative aspects of all these ideas (thinking of criticism and self-criticism in communist countries), but these limitations will need buy-in from a starting pool of people.

One thing that I have always enjoyed on G+ and blogs was posts that succinctly summarized an event, mostly during a session, or the setup of a one-shot, and discussed how they handled or solved it. This also extends to comments on other people’s activities (i.e. back to criticism). In the office, I’d talk about describing best practices and building a community of practice, but essentially, I think it needs some sort of scaffolding and we might as well call it a salon.

Thinking more about building a “community of practice”. What would that entail? I’d expect one consequence to be that we talk more about the things we do rather than about the things we make. So, while we are running games, playing games, designing games, writing games, we notice things and talk about them, instead of advertising the finished products we made. It’s less about the things we make but about the making of these things. (He says, trying to sound smart, haha.)


Add Comment

2017-11-20 No Twitter

Yeah, you’ve seen all the Mastodon posts on this blog so you know I’m using Mastodon and not Twitter. Here’s a blogpost by Jason Lefkowitz talking about the affordances of Twitter: I kind of hate Twitter.

I might not delete my account just yet, but I don’t think I’ll be posting or reading much on Twitter any time soon.

Update – talking points:

Mastodon has...

  • better moderation ✔
  • no ads ✔
  • no magic reordering of your timeline ✔
  • distributed nature ✔
  • is free software ✔
  • 500 char limit ✔

And that’s why you can find me there: @kensanata.


Add Comment



Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. Note: in order to facilitate peer review and fight vandalism, we will store your IP number for a number of days. See Privacy Policy for more information. See Info for text formatting rules. You can edit the comment page if you need to fix typos. You can subscribe to new comments by email without leaving a comment.

To save this page you must answer this question:

Please say HELLO.