Skip to content
Switch branches/tags
Go to file
This branch is 6 commits ahead of ladyofthelog:master.

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


This is my fork of alexwlchan's ao3 package, which is not actively maintained. Contributors to this include etothepii and superborb. I actively maintain this fork and welcome contributions.

A departure from the original package is that this one uses your username and cookie, rather than plaintext password entry.

  • verity (ladyofthelog)

This Python package provides a scripted interface to some of the data on AO3 (the Archive of Our Own).

It is not an official API.

This package no longer is compatible with Py2.


I want to be able to write Python scripts that use data from AO3.

An official API for AO3 data has been on the roadmap for a couple of years. Until that appears, I've cobbled together my own page-scraping code that does the job. It's a bit messy and fragile, but it seems to work most of the time.

If/when we get the proper API, I'd drop this in a heartbeat and do it properly.

  • alexwlchan


Create an API instance:

>>> from ao3 import AO3,
>>> api = AO3()

Logging into your account

Enter the contents of your _otwarchive_session cookie and username


If you have Viewing History enabled, you can get a list of works from that history.

>>> rh=api.user.reading_history()
>>> next(rh)

This returns a tuple with information about the next work in your history

Looking up information about a work

Getting a work:

>>> work ='258626')

The id is the numeric portion of the URL. For example, the work ID of is 258626.

Get a URL:

>>> work.url

You can then look up a number of attributes, similar to the Stats panel at the top of a page. Here's the full set you can look up:

>>> work.title
'The Morning After'


>>> work.summary
"<p>Delicious just can't understand why it's the shy, quiet ones who get all the girls.</p>"

>>> work.rating
['Teen And Up Audiences']

>>> work.warnings

(An empty list is synonymous with "No Archive Warnings", so that it's a falsey value.)

>>> work.category

>>> work.fandoms
['Anthropomorfic - Fandom']

>>> work.relationship

>>> work.characters
['Pinboard', 'Delicious - Character', 'Diigo - Character']

>>> work.additional_tags
['crackfic', 'Meta', 'so very not my usual thing']

>>> work.language

>>> work.published, 9, 29)

>>> work.words

>>> work.comments

>>> work.kudos

>>> for name in work.kudos_left_by:
...     print(name)
# and so on

>>> work.bookmarks

>>> work.hits

There's also a method for dumping all the information about a work into JSON, for easy export/passing into other places:

>>> work.json()
'{"rating": ["Teen And Up Audiences"], "fandoms": ["Anthropomorfic - Fandom"], "characters": ["Pinboard", "Delicious - Character", "Diigo - Character"], "language": "English", "additional_tags": ["crackfic", "Meta", "so very not my usual thing"], "warnings": [], "id": "258626", "stats": {"hits": 43037, "words": 605, "bookmarks": 99, "comments": 122, "published": "2011-09-29", "kudos": 1238}, "author": "ambyr", "category": ["F/M"], "title": "The Morning After", "relationship": ["Pinboard/Fandom"], "summary": "<p>Delicious just can\'t understand why it\'s the shy, quiet ones who get all the girls.</p>"}'

Looking up your bookmarks

If you login as a user you can look up the bookmarks for that user. You can get the bookmarks as a list of AO3 id numbers or as a list of work objects.

Warning: This is very slow as as the api has to go back and retrieve every page.

Get the bookmarks as works:

>>> for bookmark in api.user.bookmarks():
...     print(bookmark.title)
'Story Name'
'Fanfiction Title'
'Read This Fic'
# and so on

Get the bookmarks as a list of id numbers:

>>> for bookmark_id in api.user.bookmarks_ids():
...     print(bookmark_id)
# and so on


The project is licensed under the MIT license.


A scripted Python interface to some of the data on AO3




No packages published