Skip to content

Instantly share code, notes, and snippets.

@knot126
Last active November 6, 2025 21:40
Show Gist options
  • Select an option

  • Save knot126/081e1b2e411fc0d1b15dfd03cf543291 to your computer and use it in GitHub Desktop.

Select an option

Save knot126/081e1b2e411fc0d1b15dfd03cf543291 to your computer and use it in GitHub Desktop.
Unofficial fur affinity docs

UPDATE 2025-11-06: I'm making this public for historical interest, but a lot of the information here is now outdated. For example, you can now change display names and the settings have probably been changed following updates to how birthdates are handled.

Unoffical Fur Affinity documentation

This is an attempt to document how Fur Affinity works internally. This document might contain errors or be outdated by the time you are reading it, so please do not fully trust this document.

Relevant information

Fur Affinity does not have an official API, and it is not clear if they will add one. Almost every action of the site occurs via a GET or url-encoded POST request, including even things that would be better suited to an API, like managing folders.

The site is based on a custom PHP codebase originating from early 2005. After having issues in August of that year, it was (accoding to journals from the time) refactored and later relauched on 10 December 2005. The site's codebase has stayed largely the same, until an alleged refactor that started in 2021 or 2022 (source: discord messages from dragoneer on the FA discord).

Despite that there are never really situtations where a POST request would not include some given parameter and thus could throw an error, FA often does often not require that parameters are given and will set default values, including sometimes nontrivial ones.

State getting routes

This section includes any methods that get content. These largely do not change server side state; however, they might chanage state in some cases - for example, the view counter on submissions.

Browsing and information pages

GET /

Retrieve the front page HTML, which lists recent submissions.

GET /browse

Retrieve the browse page HTML with default settings. Browse is essentially a variant of the front page that allows filtering.

POST /browse

Retrieve the browse page HTML with the specified filters.

Parameters
Name Type Purpose Details Required
cat Integer Category ID
atype Integer Art type ID
species Integer Species ID
gender Integer Geneder ID
perpage Integer Number of items displayed per page
page Integer Page number to load
go String None Not actually used, sent as a conseqence of giving the form button a name attribute.
Usage
POST /browse HTTP/1.1
...

cat={category}&atype={type}&species={species}&gender={gender}&perpage={perpage}&page={page_number}&go=Apply
Notes

Not including a parameter seems to set it to 1, which coresponds to "All"/"don't apply the filter".

The go parameter is not needed and is only included becuase the form gives the button that submits it (the "Apply" button; value="Apply") a name attribute (name="go").

The integer IDs for the categories are lagrely in the same order that they appear in the dropdown, but categories added after the site's creation are often out of order, most likely since the IDs are not updateable.

TODO: What does perpage default to? The account default or a static value of 48?

Example
POST /browse HTTP/1.1
...

cat=1&atype=1&species=1&gender=0&perpage=48&page=1&go=Apply

GET /help

Get the help page HTML.

GET /advertising.html

Get the advertising info page HTML.

GET /blm

Get the Black Lives Matter info page HTML.

GET /tos

Get the terms of service page HTML.

GET /privacy

Get the prviacy policy page HTML.

GET /coc

Get the code of conduct page HTML.

GET /aup

Get the upload policy page HTML.

GET /coc

Get the code of conduct page HTML.

Submissions

GET /view/{id}

Get the page contents for the submission with the given id.

Notes
  • The submission has the id set to submissionImg.

State setting routes

State setting routes create, update or delete something server-side in a way the user would not have to think about to answer the question "Does this change something server side?".

For organisation, any route that might be a "state getting route" but is directly tied to a setting route is placed under the setting routes.

User control panel: account info

GET /controls/settings

Get the account settings form page.

POST /controls/settings

Saves account settings.

Name Type Purpose Details Required
do String Unknown, probably action to preform
fa_useremail String Account email address
bdaymonth Integer Month index of the user's birthday (1 - 12)
bdayday Integer Day of the month of the user's birthday
bdayyear Integer Year of the user's birthday Falls back to current year if not included
viewmature Integer Maxium maturity level of artwork in NSFW mode 0 = General, 2 = Mature, 1 = Adult
timezone Integer Your preferred timezone Format for dates is SHHMM from UTC: S is sign (+/-), HH is hours and MM is minutes
timezone_dst Boolean If daylight savings time corrections should be applied Excluding means disabling DST
fullview Integer Weather to display full artwork or 400px previews on submission pages
style Integer Which set of HTML templates to use
stylesheet Integer Which CSS stylesheet to use
scales_enabled Integer Enables the Shinies (dontations via paypal) 0 = Disabled, 1 = Enabled
paypal_email Integer Paypal email for the Shinies
display_mode Integer Show or hide the donation feed 0 = Show feed, 1 = Hide feed
scales_message_enabled Integer Allow users to leave messages with shinies if enabled 0 = Disabled, 1 = Enabled
scales_name String Singular name of shinies
scales_plural_name String Plural name of scales
scales_cost Integer The cost of a single shiney
account_disabled Integer If your account is disabled or not 0 = Enabled, 1 = Disabled
newpassword Integer First box to enter new password
newpassword2 Integer Second box to enter new password
oldpassword Integer Old password
Example
do=update&fa_useremail=lmao%40fucked.com&bdaymonth=1&bdayday=1&bdayyear=1995&viewmature=0&timezone=%2B0000&fullview=1&style=beta&stylesheet=ui_theme_dark&scales_enabled=0&paypal_email=&display_mode=0&scales_message_enabled=1&account_disabled=0&newpassword=&newpassword2=&oldpassword=password1234567890

General notes

Users

  • User names are not stored with underscores (_) nor are they case sensitive and are only for display purposes. The name without underscores and optionally only in lowercase is considered the artist's "lower".
  • Users have different real usernames ("lowers") and display names, but you cannot seem to update the display name.

Submissions

  • Submission IDs are incremental, starting at 1 and continuing to the current submission (51946515 as of writing).
  • The submission image URL uses the following format:
https://d.furaffinity.net/art/{lower}/{timestamp1}/{timestamp2}.{lower}_{filename}
  • lower: The artist's lower.
  • timestamp1: UNIX timestamp. This may be the creation time of the submission.
  • timestamp2: UNIX timestamp. This may be the creation time of the file.
  • filename: The original name of the file.

Examples:

  • https://d.furaffinity.net/art/jamesmiller/1631299361/1631299361.jamesmiller_20210910_154113.jpg
  • https://d.furaffinity.net/art/knot126/1679085789/1679085708.knot126_dragonised_v12.png
  • https://d.furaffinity.net/art/zell950/1682831642/1682831642.zell950_6.png

Subdomains

Subdomain Purpose
a.furaffinity.net Avatars/Profile images
d.furaffinity.net Image storage
t.furaffinity.net Thumnail image storage
rv.furaffinity.net FA community ads

Fox

There is a fox at the bottom of every page. It is a reference to a cow in a comment on an Amazon service's pages.

-
  |\ /|
 /_^ ^_\
   \v/

The fox goes "moo!"
-

Removed features

  • The original early 2005 codebase may have treated journals and font page news differently instead of using jornals for news. After the December 2005 relaunch, old news cotent was not migrated to journals and as such lost.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment