API documentation

Fluffle provides a publicly available HTTP-based API which can be used to integrate Fluffle into your own applications. Please read the next chapter (preprocessing) carefully before looking at anything else as it’s important for interacting with the API.

Preprocessing

Fluffle has been built with performance in mind. One of the many optimizations applied to Fluffle is having the client shrink the image before sending it over. This has the possibility of dramatically reducing the size of the request (great for users with slow connections), but also hugely impacts the cost of processing the image server side.

You should implement this optimization in your application too if you want to make use of Fluffle’s API. If your app’s total usage (the aggregate of all requests done by client applications that might be running) of the API is relatively low, say less than a hundred requests a day on average, then you are allowed to skip this step for convenience. However, implementing the optimization is not too much of a hassle and speeds up your requests too, so please consider it regardless.

It is recommended you shrink the image to a size where both its width and height don’t fall below 256 pixels. A few examples: 1920x1080 becomes 455x256, 1000x1000 becomes 256x256 and 700x1200 becomes 256x439. It's recommended to export the shrunken image as a PNG due to the format its lossless nature and support for transparency.

Reverse searching

POST
https://api.fluffle.xyz/v1/search

To reverse search an image, you need to send Fluffle a POST-request encoded using multipart/form-data. You must make your application identifiable by setting a custom User-Agent. It's recommended you use the following format for the User-Agent header: 'applicationName/applicationVersion (by yourName on somePlatform)'. So for example, 'Fluffle/1.2.3 (by NoppesTheFolf on Twitter)', would be a correct. If your project is open source, then instead of your personal contact details, it would preferred to instead link to where said project is hosted (like GitHub). Please keep in mind that providing your contact details is only a recommendation, you don't have to if you don't want to. These will only be used if your application is causing trouble so that we can resolve any issues it might be causing.

Parameters

KeyTypeDescription
filefileThe image to reverse search. The currently supported image formats are JPEG, PNG, GIF and WebP. The size of the provided image must not exceed 4 MiB, nor should the image its dimensions exceed a total area (width * height) of 16 million pixels (16MP). You should abide by the image preprocessing policy as described in the previous chapter.
includeNsfwbooleanAn optional boolean value indicating whether or not Fluffle should also search through images deemed Not Safe For Work. By default, Fluffle will not search NSFW images. Fluffle is unable to reliably determine if images from Twitter are NSFW or not. Therefore, to play it safe, all images are considered explicit by default. You should include NSFW results if you want to use Twitter as a source.
platformsstring[]The platforms to be included in the reverse search process. Currently supported platforms are Fur Affinity, Twitter, e621, Weasyl, Furry Network, DeviantArt and Inkbunny. Not providing this field will cause all of the aforementioned platforms to be included. Make sure your application can deal with new platforms: the API its version will not be increased if it is decided to add support for another platform. An alternative would be to send a list of all platforms your application supports with each request. The values provided to this field are casing-insensitive, meaning you can pass them snake cased, camel cased, or whatever you prefer.
limitintegerBy default, Fluffle will send you a maximum of 32 results. You can tweak this number by providing a value from 8 to 32. Exceeding this range will cause your request to fail.
createLinkbooleanWhether or not Fluffle should store your search result indefinitely and make it accessible through a link. This parameter defaults to false. After all, it takes up resources to make the search result available. Because of this, please do not set this value to true if a user did not (implicitly or explicitly) request the search result to be used this way. The response will contain an ID. Appending this ID to the end of https://fluffle.xyz/q/ will allow the search result to be viewed in a browser.

Example request

Alright, that’s enough documentation… let’s see some code! The code below is a small script written in Python which preprocesses the image “fluffy-critter.png” and reverse searches it using Fluffle its API. You can use this as reference material for implementing Fluffle its API in your programming language of choice.

import io
from pprint import pprint
from PIL import Image
from requests import post

# Preprocess the image as per Fluffle its documentation
image = Image.open("fluffy-critter.png")
width, height = image.size


def calculate_size(width, height, target):
    def calculate_size(d1, d2, d1_target): return round(d1_target / d1 * d2)

    if width > height:
        return calculate_size(height, width, target), target

    return target, calculate_size(width, height, target)


image.thumbnail(calculate_size(width, height, 256))
buffer = io.BytesIO()
image.save(buffer, "png")

# And then reverse search the preprocessed image
headers = {
    "User-Agent": "api-demo/1.0 (by NoppesTheFolf on Twitter)"
}
files = {
    "file": buffer.getvalue()
}
data = {
    "platforms": [
        "fur affinity",
        "furry network"
    ],
    "limit": 8
}

response = post("https://api.fluffle.xyz/v1/search", headers=headers, files=files, data=data).json()
pprint(response)

Responses

The chapter below describes all of the responses you can get from the API. Please note that there is no guarantee that you will always receive a JSON structure as a response on errors because the API is running behind Cloudflare.

200
OK

Your request was valid and could therefore be processed. The submitted image has been compared against all (specified) platforms and the results said comparison yielded are embedded in the body of the request.

Example response

{
  "id": "CJKVQ9TGyakVCkvtC",
  "stats": {
    "count": 18311838,
    "elapsedMilliseconds": 402
  },
  "results": [
    {
      "id": 1344062,
      "score": 0.966796875,
      "match": "exact",
      "platform": "e621",
      "location": "https://e621.net/posts/546281",
      "isSfw": true,
      "thumbnail": {
        "width": 300,
        "centerX": 0,
        "height": 400,
        "centerY": 37,
        "location": "https://static.fluffle.xyz/file/fluffle/0e2c770cf4a9eccb7f16570f5586aa9d.jpg"
      },
      "credits": [
        {
          "id": 123,
          "name": "lycanruff"
        }
      ]
    }
  ]
}

Schema


400
Bad Request

The request you sent over to Fluffle is invalid. The response body will tell you what you did wrong and how you can resolve the issue. For example, requesting Fluffle to search for images on a non-existent platform will cause such a response. These errors can always be prevented by properly implementing the API. They are only meant to give guidance to developers.

{
  "code": "VALIDATION_FAILED",
  "message": "One or more validation errors occurred.",
  "errors": {
    "platforms": [
      "Platform with the name 'some platform name' either doesn't exist or is not supported."
    ]
  }
}

400
Bad Request

The submitted image its area exceeded the 16MP limit.

{
  "code": "AREA_TOO_LARGE",
  "message": "An informational message for developers."
}

413
Payload Too Large

There are a couple of variations of this response due to Fluffle running behind Cloudflare. You can get a JSON one generated by Fluffle if your image exceed the 4 MiB limit and a HTML one by Cloudflare if you exceed their limit. You shouldn't have to handle this response if you just make sure the image you send over isn't larger than 4 MiB. If you do wish to handle the response, then you should use the status code.

{
  "code": "FILE_TOO_LARGE",
  "message": "An informational message for developers."
}

415
Unsupported Media Type

The image embedded in the request couldn't be processed due to it not being encoded in a supported format. Currently JPEG, PNG. GIF and WebP are supported. Support for AVIF might be added in a future release.

{
  "code": "UNSUPPORTED_FILE_TYPE",
  "message": "An informational message for developers."
}

422
Unprocessable Entity

The image embedded in the request got recognized as being encoded in a supported format, but it couldn't be read in said format. Therefore, the image couldn't be processed and is deemed corrupt.

{
  "code": "CORRUPT_FILE",
  "message": "An informational message for developers."
}

500
Internal Server Error

Something unexpected happened which made the server unable to fulfil the request. The response will contain a so-called trace ID which may prove useful when trying to determine the root cause of the error. You may choose to contact the grumpy folf - don’t worry, I won’t bite - who made Fluffle so that the issue can be solved. Please make sure you can provide the trace ID sent along with the request if you choose to do so!

{
  "code": "KABOOM",
  "message": "Now you have become death, the destroyer of applications.",
  "traceId": "12345678-01"
}

503
Service Unavailable

Fluffle is unable to fulfil your request at this moment. This can be the case due to a variety of reasons. One being for example that the server assigned to process your request has restarted (unexpectedly) and is still getting ready. It should be noted that this response is extremely rare as downtime is limited as much as possible, of course. It is worth retrying the request after some time as it will succeed eventually. You should consider waiting at least 10 seconds before giving it another shot.

{
  "code": "UNAVAILABLE",
  "message": "An informational message for developers."
}

5xx
Cloudflare

Due to Fluffle running behind Cloudflare, there are various other status codes you might want to deal with. A complete list of status codes used by Cloudflare can be found on their support page. It's a good idea to treat the 502, 504, 521, 522, 523 and 524 status codes as transient errors (and are therefore worth retrying), just like 503 responses. Keep in mind that Cloudflare doesn't give you a JSON response.