← Back

Monbooru API

Version 1.1.0 · base URL https://booru.grinev.dev/api/v1

API is disabled - generate a token in Settings → Authentication to enable it. All endpoints currently return 503 api_disabled.

Every endpoint except /docs and /openapi.json requires Authorization: Bearer <token>. Create a named token in Settings → Authentication; while none exists every authenticated endpoint returns 503 api_disabled. Tokens are scoped (read/write/delete); a request whose token lacks the scope gets 403 insufficient_scope.

Endpoints take an optional ?gallery=<name> (or X-Monbooru-Gallery header) to target a specific gallery; omit both for the active one.

Raw spec: openapi.json

Endpoints

GET/

API info

Responses

StatusDescriptionSchema
200API metadataAPIInfo
503API disabled (no token configured)Error

GET/categories

List tag categories

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Categories

POST/categories

Create a category

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: name

FieldTypeDescription
colorstring#rgb or #rrggbb; defaults to #888888 when blank.
namestringLowercase letters, digits, underscore, or hyphen. Search-filter keywords are reserved.

Responses

StatusDescriptionSchema
201Created categoryCategory
400Invalid or reserved name, or invalid colourError
409A category with this name already existsError

PATCH/categories/{id}

Rename and/or recolor a category

Parameters

NameInRequiredDescription
idpathyesCategory ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

FieldTypeDescription
colorstring#rgb or #rrggbb. Allowed on built-in categories.
namestringNew name. Built-in categories refuse a rename.

Responses

StatusDescriptionSchema
200Updated categoryCategory
400No fields, invalid colour, reserved/invalid name, or a built-in renameError
404Category not foundError
409A category with the new name already existsError

DELETE/categories/{id}

Delete a category

Parameters

NameInRequiredDescription
idpathyesCategory ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

FieldTypeDescription
actionstring'move' (default; reparent the category's tags) or 'delete_all' (drop the tags too).
target_idintegerMove target category id; defaults to general when omitted.

Responses

StatusDescriptionSchema
204Deleted
400Built-in category, or an unknown actionError
404Category not foundError

GET/galleries

List configured galleries

Responses

StatusDescriptionSchema
200Galleries with counts and the active flag

POST/images

Add an image

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: path

FieldTypeDescription
autotagbooleanKick off an auto-tag job on the new image
collectionstringOptional collection label (images.series). Written on the new row; on a duplicate-SHA push added as a membership that never displaces the existing home.
collection_orderintegerOptional 1-based position within the collection. Requires a non-empty collection in the same request.
commentarystringOptional artist commentary for the pushed source (<=10000 chars).
folderstringDestination subfolder for relative paths
md5stringOptional md5 the source claims for the file (<=64 chars). Recorded on the origin row as an audit trail; never a dedup key.
notesarrayOptional positional note boxes ({x, y, w, h, body}) for the pushed source.
originalstringOptional upstream artist source the post declared (<=2048 chars, newline-joined when several). Recorded on the same origin as 'source'.
parent_urlstringOptional canonical URL of the post this post declares as its parent. Must start with http:// or https://. Recorded on the same origin as 'source'; when the parent's post lands in the gallery too, the pair is linked as a derivative relation.
pathstringPath to a file already on disk. Absolute paths are used verbatim; relative paths are resolved under gallery/<folder> when folder is set, otherwise under the gallery root. WARNING: absolute paths give a token holder read access to anything the monbooru process can stat.
sourcestringOptional site label for the image's origin (site name, scraper...). Recorded as a source; on a duplicate-SHA push its tags and provenance merge into the existing image instead of being discarded.
tagger_namestringOptional auto-tagger name
tagsarray
urlstringOptional canonical web URL the image came from. Must start with http:// or https://. Recorded on the same origin as 'source'.
viastringOptional caller-supplied identifier. Stored as images.origin and attached to each initial tag. Blank defaults images.origin to 'ingest' for JSON path-reference mode.

Content-Type: multipart/form-data

Required: file

FieldTypeDescription
autotagstringSet to "true" to kick off an auto-tag job on the new image
collectionstringOptional collection label (images.series). Written on the new row; on a duplicate-SHA push added as a membership that never displaces the existing home.
collection_orderstringOptional 1-based position within the collection. Requires a non-empty collection in the same request.
commentarystringOptional artist commentary for the pushed source (<=10000 chars).
filestringImage or video file
folderstringDestination subfolder under the gallery root; missing directories are created. Leave blank for the gallery root.
md5stringOptional md5 the source claims for the file (<=64 chars). Recorded on the origin row as an audit trail; never a dedup key.
notesstringOptional JSON-encoded array of positional note boxes ({x, y, w, h, body}) for the pushed source.
originalstringOptional upstream artist source the post declared (<=2048 chars, newline-joined when several). Recorded on the same origin as 'source'.
parent_urlstringOptional canonical URL of the post this post declares as its parent. Must start with http:// or https://. Recorded on the same origin as 'source'; when the parent's post lands in the gallery too, the pair is linked as a derivative relation.
sourcestringOptional site label for the image's origin (site name, scraper...). Recorded as a source; on a duplicate-SHA push its tags and provenance merge into the existing image instead of being discarded.
tagger_namestringOptional auto-tagger name; when set with autotag, restricts the job to that tagger
tagsstringJSON-encoded array of tag names
urlstringOptional canonical web URL the image came from. Must start with http:// or https://. Recorded on the same origin as 'source'.
viastringOptional caller-supplied identifier (app name, URL...). Stored as images.origin and attached to each initial tag via image_tags.tagger_name. Blank defaults images.origin to 'upload' for multipart mode.

Responses

StatusDescriptionSchema
200Duplicate SHA-256: existing image returned with the pushed tags and provenance merged; alias_added is true only when a JSON path-reference recorded a new aliasDuplicateImageResponse
201Image createdCreateImageResponse
400Invalid request or unsupported file typeError
413File exceeds max sizeError
500Ingest failureError

Search images

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)
qquerynoSearch query (tag list, filters, wildcards)
sortquerynoSort field: newest, filesize, order, random
orderquerynoSort order: asc, desc
seedquerynoRandom-sort seed for stable pagination when sort=random
pagequerynoPage number (1-based)
limitquerynoResults per page (max 200)

Responses

StatusDescriptionSchema
200Paginated image listPaginatedImages

GET/images/{id}

Get image metadata

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Image metadataImage
404Not foundError

PATCH/images/{id}

Edit image fields

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

FieldTypeDescription
collectionstringCollection label (images.series). Empty clears.
collection_orderinteger1-based position within the collection. Requires a non-empty collection (incoming or already stored).
is_favoritedboolean
is_inboxbooleantrue = sits in the inbox (needs triage); false = curated.
sourcestringOperator-edited provenance label (<=200 chars). Empty clears.
urlstringCanonical web URL (<=2048 chars, http:// or https://). Empty clears.

Responses

StatusDescriptionSchema
200Updated imageImage
400Invalid request (bad url, order without a collection, or no editable fields supplied)Error
404Not foundError
409Relabel collides with another origin the image already carriesError

DELETE/images/{id}

Delete image from library

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)
delete_empty_folderquerynoRemove containing folder if empty after deletion

Responses

StatusDescriptionSchema
200Deleted (folder also removed)
204Deleted
404Not foundError

POST/images/{id}/enrich

Apply fetched metadata to an existing image

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

FieldTypeDescription
commentarystring
notesarrayPositional note boxes ({x, y, w, h, body}); a non-empty array replaces the set this origin contributed.
originalstringUpstream artist source the post declared (<=2048 chars, newline-joined when several). A non-empty value overwrites the stored one.
parent_urlstringCanonical URL of the post this post declares as its parent. Recorded on the origin row; when both sides are in the gallery the pair is linked as a derivative relation. Empty keeps the stored value.
similaritynumberSimilarity-service score (0-100) when the post was found by image similarity rather than an exact hash. Recorded on the origin row; a matched origin's refetches skip the md5 verify. 0 or absent keeps the stored score.
sourcestringSite label of the origin being refetched
source_md5stringmd5 the source claims (<=64 chars). Compared against the stored file when verify is set; recorded on the origin row.
tagsarray
urlstring
verifybooleanWhen true and source_md5 is non-empty, the stored file is hashed and compared first; a mismatch applies nothing and returns 409 - unless the origin is similarity-matched, whose file differs by design.

Responses

StatusDescriptionSchema
200Metadata appliedEnrichResponse
404Not foundError
409Hash mismatch: the source no longer serves this file; nothing was changed. Not raised for a similarity-matched originError
500A merge write failed (recorded as an error fetch status)Error

POST/images/{id}/fetch-status

Report a source-fetch outcome

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: state

FieldTypeDescription
messagestringOperator-facing detail shown on the image's fetch pill
statestringOutcome state, e.g. "error"

Responses

StatusDescriptionSchema
200Recorded
400Missing stateError

GET/images/{id}/file

Download original image/video bytes

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Original file bytes
404Not foundError

GET/images/{id}/page/{n}

Download a manga page (cbz rows)

Parameters

NameInRequiredDescription
idpathyesImage ID
npathyes1-based page number
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Page bytes (lazily extracted from the archive)
400Invalid page numberError
404Not a manga row, or page out of rangeError

GET/images/{id}/page/{n}/thumb

Download a manga page thumbnail (cbz rows)

Parameters

NameInRequiredDescription
idpathyesImage ID
npathyes1-based page number
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Page thumbnail (JPEG)
400Invalid page numberError
404Not a manga row, or page out of rangeError

GET/images/{id}/relations

Get declared relations for an image

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Declared relationsImageRelations
404Image not foundError

GET/images/{id}/tags

List image tags

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Image tag listTagArray
404Not foundError

POST/images/{id}/tags

Add tags to image

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: tags

FieldTypeDescription
tagsarrayTag names to add
viastringOptional caller-supplied identifier attached to each added tag (app name, URL...); stored in image_tags.tagger_name so the detail page can surface which third party contributed them

Responses

StatusDescriptionSchema
200Bare TagArray on success; wrapped in {tags, tag_warnings} when any tag failed validation.

DELETE/images/{id}/tags

Remove tags from image

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: tags

FieldTypeDescription
tagsarrayTag names to remove

Responses

StatusDescriptionSchema
200Updated tag listTagArray

GET/images/{id}/thumbnail

Download the static thumbnail

Parameters

NameInRequiredDescription
idpathyesImage ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200JPEG thumbnail
404Image or thumbnail not foundError

POST/relations

Declare a relation

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: type a b

FieldTypeDescription
aintegerLeft image id. For directed types (version, derivative), `a` is the parent / source (older revision, derived-from).
bintegerRight image id. For directed types, the child / derivative.
directionstringOptional `ba` swaps left/right; default `ab` treats `a` as the parent/source side.
typestringOne of: duplicate, alternate, version, derivative, not_related

Responses

StatusDescriptionSchema
201Relation created
400Invalid request (self-relation, unknown type, missing ids)Error
409Pair carries a conflicting relation already; remove it first.Error

DELETE/relations

Remove a declared relation

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: type

FieldTypeDescription
aintegerRequired for version / derivative / not_related; either order is accepted.
bintegerPair partner for a.
group_idintegerRequired for dissolve_dup / dissolve_alt / promote_original.
image_idintegerRequired for duplicate / alternate (the member to unlink); the new original for promote_original.
root_idintegerRequired for dissolve_version / dissolve_derivative; any chain or tree member id (the walker locates the root).
typestringOne of: duplicate, alternate, version, derivative, not_related, dissolve_dup, dissolve_alt, dissolve_version, dissolve_derivative, promote_original

Responses

StatusDescriptionSchema
204Removed (idempotent)
400Invalid requestError

GET/tags

List tags

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)
qquerynoPrefix filter
categoryquerynoFilter by category name
sortquerynoSort field (usage, alpha)
pagequerynoPage number
limitquerynoResults per page (default 100, max 500)
show_zeroquerynoHide zero-usage non-alias tags ('0' to opt out). Default surfaces them so the API total matches the /tags page total.
originquerynoFilter by stored creation origin ('user', a booru site, 'ptr', an auto-tagger name, ...). The legacy 'alias' value narrows to alias rows. Empty (default) returns every tag.
typequerynoStructural filter: 'tag' (non-alias rows), 'alias' (alias rows). Empty (default) returns both.

Responses

StatusDescriptionSchema
200Paginated tag listPaginatedTags

POST/tags

Create a tag (get-or-create)

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: name

FieldTypeDescription
categorystringCategory name; defaults to general.
namestring

Responses

StatusDescriptionSchema
201The tag (created, or the existing row when the name already exists in the category)TagRow
400Missing name, unknown category, or invalid tag nameError

POST/tags/aliases

Create an alias

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: name canonical_id

FieldTypeDescription
canonical_idintegerThe tag this alias resolves to.
categorystringCategory for the alias; defaults to general.
namestringAlias name.

Responses

StatusDescriptionSchema
201The alias rowTagRow
400Missing fields or an invalid alias targetError
404Canonical tag not foundError
409The name already names a tag with image_tags rows; merge it insteadError

POST/tags/merge

Merge one tag into another

Parameters

NameInRequiredDescription
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: alias_id canonical_id

FieldTypeDescription
alias_idintegerTag to retire; becomes an alias of canonical_id and its image_tags move onto it.
canonical_idintegerSurviving tag.

Responses

StatusDescriptionSchema
200The canonical tagTagRow
400Self-merge, missing ids, or a merge into an aliasError

PATCH/tags/{id}

Rename a tag and/or move it to another category

Parameters

NameInRequiredDescription
idpathyesTag ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

FieldTypeDescription
categorystringMove to this category by name.
namestringNew name.

Responses

StatusDescriptionSchema
200Updated tagTagRow
400No fields supplied, or a rating-tag editError
404Tag not foundError
409A tag with the new name already exists in the target categoryError

DELETE/tags/{id}

Delete a tag

Parameters

NameInRequiredDescription
idpathyesTag ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
204Deleted (rating-category rows are usage-stripped; the catalog row stays)
404Tag not foundError

GET/tags/{id}/implications

List a tag's implications

Parameters

NameInRequiredDescription
idpathyesParent tag ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
200Direct implications
404Parent tag not foundError

POST/tags/{id}/implications

Declare an implication

Parameters

NameInRequiredDescription
idpathyesParent tag ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Request body

Content-Type: application/json

Required: implied_id

FieldTypeDescription
implied_idintegerExisting tag id the parent implies. Both sides must be canonical (non-alias).

Responses

StatusDescriptionSchema
200Edge already declared (no-op)
201Edge created
400Missing implied_id, self-implication, or an alias on either sideError
404Parent or implied tag not foundError
409Edge would close a cycleError

DELETE/tags/{id}/implications/{impliedID}

Remove an implication

Parameters

NameInRequiredDescription
idpathyesParent tag ID
impliedIDpathyesImplied tag ID
galleryquerynoTarget gallery name; omit for the active gallery (also accepted as X-Monbooru-Gallery header)

Responses

StatusDescriptionSchema
204Removed
404Edge not foundError

Schemas

APIInfo

FieldTypeDescription
apistring
docsstring
openapistring

Category

FieldTypeDescription
colorstring
idinteger
is_builtinboolean
namestring

CreateImageResponse

FieldTypeDescription
autotagstring · nullableHuman-readable status about the auto-tag job
image
tag_warningsarray · nullable

DuplicateImageResponse

FieldTypeDescription
alias_addedbooleanTrue when the posted path was recorded as an alias of the existing image (JSON path-reference); false when a redundant multipart upload was discarded
image
merge
tag_warningsarray · nullable

EnrichResponse

FieldTypeDescription
merge
tag_warningsarray · nullable
verifiedbooleanFalse when verify was requested but the source reported no md5

Error

FieldTypeDescription
codestring
errorstring
FieldTypeDescription
activebooleanTrue for the gallery used when no ?gallery= selector is given
imagesintegerVisible (non-missing) image count
namestring
tagsintegerNon-alias tag count

Image

FieldTypeDescription
aliasesarray
annotationsarrayPositional note boxes pulled per source, in original-image pixel coordinates. Omitted when empty.
auto_tagged_atstring · nullable
canonical_pathstring
collectionstringHome collection label - mirrors the first entry of 'collections'. Empty string when unset. Filtered by the search keyword 'collection:' (exact match). Settable on create and via PATCH /images/{id}.
collection_orderinteger · nullable1-based position within the home collection. Null when unset. Settable on create and via PATCH /images/{id}.
collectionsarrayEvery collection the image belongs to. The scalar collection / collection_order fields mirror the home membership. Managed through the web UI; the API sets only the home via collection / collection_order.
file_sizeinteger
file_typestring
heightinteger · nullable
idinteger
ingested_atstring
is_favoritedboolean
is_inboxbooleantrue = needs triage (sits in the inbox); false = curated. New ingests default to true.
is_missingboolean
notestringOperator's freeform note. Never written by a push, enrich, or import.
originstringHow the image got into the gallery: 'ingest' for watcher/sync, 'upload' for the web UI, or any caller-supplied string (app name, URL...) set via POST /images with 'via'
original_sourcestringOperator's image-level original source URL. Never written by a push, enrich, or import.
page_countinteger · nullableNumber of pages for cbz / manga rows; null on every other file type.
phashstring · nullable16-char hex perceptual hash; null until the phash backfill or ingest has populated it.
sha256string
sourcestringSite label of the primary (first) entry of 'sources'. Empty string when the image has no origin. Filtered by the search keyword 'source:' which matches any of the image's sources. Settable on create and via PATCH /images/{id}.
source_typestringGeneration-tool source: 'a1111', 'comfyui', 'a1111,comfyui', or 'none'. Filtered by the search keyword 'ai:'.
sourcesarrayEvery origin the image came from. The scalar source / url fields mirror the primary (first) origin. Managed through the web UI; the API sets only the primary via source / url.
tagsarray
thumbnail_urlstring
urlstringURL of the primary (first) entry of 'sources'. Empty string when the image has no origin. Must start with http:// or https://. Settable on create and via PATCH /images/{id}.
widthinteger · nullable

ImageRelations

FieldTypeDescription
alternate_groupobject · nullable
derivative_sourceinteger · nullableid of the source image when this image is a derivative; null otherwise.
derivativesarray
duplicate_groupobject · nullable
version_childinteger · nullableid of the newer revision; null when this image is the chain leaf.
version_parentinteger · nullableid of the older revision; null when this image is the chain root.

Implication

FieldTypeDescription
implied_categorystring
implied_idinteger
implied_namestring
parent_idinteger

MergeSummary

FieldTypeDescription
rating_filledbooleanTrue when the push supplied a rating and the image had none; an existing rating is never displaced
source_addedboolean
tags_addedinteger
tags_removedintegerTags this source contributed earlier and no longer lists

PaginatedImages

FieldTypeDescription
limitinteger
pageinteger
resultsarray
totalinteger

PaginatedTags

FieldTypeDescription
limitinteger
pageinteger
resultsarray
totalinteger

Tag

FieldTypeDescription
categorystring
confidencenumber · nullable
is_autoboolean
namestring
tagger_namestring · nullableProvenance identifier: auto-tagger subfolder name when is_auto, caller-supplied 'via' (e.g. app name) when manual, null for UI-driven user adds

TagArray

(no fields)

TagRow

FieldTypeDescription
categorystring
colorstring
idinteger
is_aliasboolean
last_used_atstringISO 8601; most recent application to an image. Absent when never applied.
namestring
originstringCreation provenance label: 'user', a booru site, 'ptr', an auto-tagger name, an import label. Empty on rows predating the column.
usage_countinteger