Admittedly, the more obvious question is perhaps not how but why. While testing the script below I came across a comment I’d left early in 2022 talking about how great Dreamwidth was and how I loved it so much, but I’m increasingly convinced that most of my opinions come with expiry dates. At that stage in my life I was very keen on the idea of seeking out anyone who’d ever written Final Fantasy fanfiction and having substantial conversations with them about minute details of the games, but over time the allure faded as I realised most of those people usually wanted to post about their lives instead … the blend of fandom talk and personal talk is something I find hard to navigate, this being one of the various reasons why I also deleted my Discord account a few months ago. I would actually like to talk to people about fandom stuff without having to be considered their “friend” first, but the reading-list access-list culture of Dreamwidth makes this difficult to do on personal journals. Moreover, most communities are extremely inactive such that when you get the occasional reply from a melter, it’s like 50% of any replies you get within a week, which is also not especially pleasant.
In general, I’ve been deleting my accounts on third-party websites where possible anyway, now that I can do pretty much everything I care about on my own domain. Dreamwidth is ultimately just another silo – one that doesn’t have advertising and tracking, sure, but still another American website with an infrastructure I am largely unable to modify and a set of intricate and confusing social norms (at least, such as I understand it, which is obviously what is most salient in terms of my own personal experience, even if those less neurotic than I am may have the good fortune to see it as 100% chill). As far as I’m aware, there has been limited discussion of implementing some federation-related features such as fediverse/ActivityPub compatibility and IndieAuth as a replacement for OpenID (which is pretty much dead, Ask Me How I Know), but these clearly aren’t priorities.
I always try to remove my posts from a given website before embarking on account deletion adventures, if the deletion process itself doesn’t wipe them for me (yes I went through every single Discord message I’d sent in each server and removed them one by one … fortunately I am not especially talkative). On Dreamwidth, comments from deleted accounts remain visible, but I really didn’t want to have my various hot takes floating around the internet in ways beyond my control for years afterwards, especially not associated with a username that people may be able to trace to me, and especially not when a number of the comments I left in 2022 were written with an “I want to be friends with everyone who has ever played a Final Fantasy game” mentality. People change, even within three years – oddly, though, one of the things that has never changed about me is my desire to delete my data as thoroughly as possible from websites I’m no longer using.
Dreamwidth has a “comment management” function, which shows users a list of their comments allowing quick access to them for deletion, but even for paid accounts it only shows the latest 150, including those that have already been deleted. This doesn’t allow us to make a huge amount of progress towards the goal of erasing our existence from Dreamwidth as thoroughly as possible. Instead, that goal has to be met with the assistance of two familiar methods: obscure use of the specific features the site itself provides, and … writing a weird Python script.
I actually did the “obscure use of site features” part before the “weird Python script” part, which was quite a significant mistake because there are now a lot of comments left by my account on posts I no longer have access to, so I’m not able to delete them. I am less bothered by this than I would be about comments on public posts, and at least these comments are no longer transparently associated with a username people might recognise as me. Probably quite a lot of them say things like “I live in Northern Ireland and I love Auron a lot”, so those who remember me wouldn’t find it too hard to guess, but it could be worse. Anyway, ideally, this part of the process would come first.
Firstly, identifying one’s own posts in communities is easy to do by appending ?poster=USERNAME
to the end of the comm URL, so those can be deleted manually in every community to which one has posting access (listed on one’s profile). If there are any posts not deleted at this stage (mod posts in a comm that now belongs to somebody else, for example), the below script will erase all comments on these posts, not just one’s own. So if one has posts in a community and wants to retain both those posts and any comments on them, leave that community out of the list of journals to delete from.
Once that’s done, the following script iterates through a list of journals and communities, checks each post for one’s comments, and deletes them. Before running the script, it’s necessary to log into the account and set journals and posts to display in the site style (this can be done even after the account has been deleted). It also occasionally fails for reasons unknown on page whatever of a post with multiple comment pages – in cases like this, it just gives up on that journal and moves on to the next one, which I thought was less disruptive than dying completely. This is only a potential issue in cases like /threesentenceficathon where there are enormous numbers of comments – a benefit of DW being relatively low in activity.
The list of journals and comms would normally be based on one’s subscription list, assuming that’s where one would have been commenting; it was slightly more laborious for me because I’d been using RSS instead of the reading page to subscribe for some time, so I had to export the list from my RSS reader and do some regexing to cut it down to just Dreamwidth URLs. (And I should probably clarify this somewhere, so I guess here will do: I am still reading DW journals/comms via RSS and occasionally commenting “anonymously”, although as noted, I can no longer see access-locked posts.)
Also, I guess the other unaccounted-for edge case is that if someone’s journal has a sticky and that sticky is also their most recent post and there are relevant comments on that post, they won’t be picked up. This seems like it would be pretty rare though.
Here is the script. I’m sorry about the indentation in the exported version, org-mode is always weird about this. I also don’t even know if all those instances of time.sleep()
need to be in there … I just guess places where they might need to go in and stick in some arbitrary delay, but it may work fine without them. There are some weird things involving lists, but I found that iterating over comments in a more obvious way didn’t always work; Selenium appears to have a lot of idiosyncrasies.
from selenium.common import exceptions from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium import webdriver import time theuser = "USERNAME" thepass = "PASSWORD" targets = ["journal1","journal2","journal3","et cetera"] # just the username, no .dreamwidth.org, hyphens not underscores startyear = 2022 # year the first comments were left browser = webdriver.Firefox() browser.get("https://www.dreamwidth.org/login") username = browser.find_element(By.ID,"user") username.send_keys(theuser) password = browser.find_element(By.ID,"lj_loginwidget_password") password.send_keys(thepass) password.send_keys(Keys.RETURN) time.sleep(5) for target in targets: browser.get("https://" + target + ".dreamwidth.org") time.sleep(3) firstentry = browser.find_element(By.XPATH,"//h3[contains(@class,'entry-title') and not(contains(@class, 'sticky-entry-title'))]") firstentry.click() time.sleep(3) date = browser.find_element(By.CLASS_NAME,"datetime") try: while (int(date.text[0:4])) >= startyear: try: expand = browser.find_element(By.CLASS_NAME,"expand_all") expand.click() time.sleep(5) except: pass try: deletes = browser.find_elements(By.CLASS_NAME,"delete_comment") except: deletes = [] if len(deletes) > 1: goback = False else: goback = True while len(deletes) > 0: try: deletes[0].click() confirm = browser.find_element(By.CLASS_NAME,"ui-button") confirm.click() except: deletes = [] time.sleep(2) if goback: try: thenext = browser.find_element(By.XPATH,"//li[contains(@class,'page-next') and not(contains(@class, 'disabled'))]") thenext.click() except: backbutton = browser.find_element(By.CLASS_NAME,"link_prev") backbutton.click() else: browser.refresh() try: date = browser.find_element(By.CLASS_NAME,"datetime") except: date = 0 break time.sleep(2) except exceptions.StaleElementReferenceException: time.sleep(10) browser.quit()
It takes a long time to run. I’ve had it running most of the day and it’s still in the very early part of my list, going through every post, but if I need to stop it I can take whichever journals have already been done off the list so it doesn’t waste time going through them again.
Even if one’s account and nearly all one’s coments are deleted, one’s username will still show up in people’s access lists etc. There is no way of forcing someone to stop subscribing to a journal, or of removing oneself from an access list (unlike on some fediverse software where you can “remove followers”, or on e.g. Tumblr where softblocking is a productive strategy). However, the account rename option comes with the ability to sever one’s connections with other journals; as I remember, it’s just a case of leaving all boxes unticked and then the journal will be removed from everyone’s access lists and reading pages.
This does cost money (it was about 12 quid when I did it), but it seemed worth it for the ability to both remove my account from other people’s profiles and change the username associated with any comments I wasn’t able to delete. The account has to be active before being renamed: I had already deleted mine and had to reactivate it, rename, and then delete again, but this is a very easy and quick process.
Doing this leaves the original username exposed to the possibility of registration as a new account, but I think it’s unlikely that anyone is going to feel the need to impersonate me.