API Docs/DeArrow
The DeArrow API is free to use for all non browser-extensions
If you end up using the API, I'd love to know about how you're using it. Tell me about it by making a GitHub issue or emailing me :)
Automating Submissions is not allowed.
The API and database follow this license unless you have explicit permission. Attribution Template
Public API available at https://sponsor.ajay.app.
Database download: https://sponsor.ajay.app/database
Database Mirror (30 min update time, provided by Lartza): https://sb.ltn.fi/database/
Database Mirror (10 min update time, provided by blab): https://mirror.sb.mchang.xyz/
Database Mirror (90 min update time, provided by mini_bomba): https://sb.minibomba.pro/mirror/
Note: Database mirrors listed above do NOT provide an API for the extensions. Setting the server address to any of these URLs will result in no segments or video details being shown.
DeArrow-only read-only API Mirror (90 min update time, provided by mini_bomba): https://dearrow.minibomba.pro/sbserver/
Libraries: Kotlin
GET /api/branding
Get submission for a video.
Note: Data is returned in order of quality. You can use the first element. However, you should make sure the first element has either locked = true or votes >= 0. If not, it is considered untrusted and is only to be shown in the voting box until it has been confirmed by another user.
Random time and video duration are used if you want to fallback thumbnails to a screenshot from a random time. To make thumbnail caching possible, this random time is consistent and produced by the server. The random time value is a number between 0 and 1 and must be multiplied by the video duration. For convenience, the API returns the video duration if it is known, but for most videos the server does not know the video duration. When the API returns a video duration of 0 or null, you must either not use this feature, or obtain the video duration using another method. The browser extension will fallback to fetching the video duration using other methods to always be able to use the feature.
Input (URL Parameters):
{
videoID: string,
service: string, // Optional, default is 'YouTube' [1]
returnUserID: boolean, // optional, returns submitter userIDs if true, default false
fetchAll: boolean // optional, hides details with negative score if false, default false
}
References: [1] Response:
{
titles: Array<{
title: string, // Note: Titles will sometimes contain > before a word. This tells the auto-formatter to not format a word. If you have no auto-formatter, you can ignore this and replace it with an empty string
original: boolean,
votes: number,
locked: boolean,
UUID: string,
userID: string // only present if requested
}>:
thumbnails: Array<{
timestamp: number, // null if original is true
original: boolean,
votes: number,
locked: boolean,
UUID: string,
userID: string // only present if requested
}>
randomTime: number,
videoDuration: number | null
}
Error codes:
400: Bad Request (Your inputs are wrong/impossible)
404: Not Found
GET /api/branding/:sha256HashPrefix
Get submissions for a video.
sha256HashPrefix
is a hash of the YouTube videoID
. It should be the first 4 characters. This provides extra privacy by potentially finding more than just the video you are looking for since the server will not know exactly what video you are looking for.
Note: Data is returned ordered. You can use the first element. However, you should make sure the first element has either locked = true or votes >= 0. If not, it is considered untrusted and is only to be shown in the voting box until it has been confirmed by another user.
Random time and video duration are used if you want to fallback thumbnails to a screenshot from a random time. To make thumbnail caching possible, this random time is consistent and produced by the server. The random time value is a number between 0 and 1 and must be multiplied by the video duration. For convenience, the API returns the video duration if it is known, but for most videos the server does not know the video duration. When the API returns a video duration of 0 or null, you must either not use this feature, or obtain the video duration using another method. The browser extension will fallback to fetching the video duration using other methods to always be able to use the feature.
Input (URL Parameters):
{
service: string // Optional, default is 'YouTube'. [1]
returnUserID: boolean, // optional, returns submitter userIDs if true, default false
fetchAll: boolean // optional, hides details with negative score if false, default false
}
References: [1] Response
{
[videoID: string]: {
titles: Array<{
title: string,
original: boolean,
votes: number,
locked: boolean,
UUID: string,
userID: string // only present if requested
}>:
thumbnails: Array<{
timestamp: number, // null if original is true
original: boolean,
votes: number,
locked: boolean,
UUID: string,
userID: string // only present if requested
}>,
randomTime: number,
videoDuration: number | null
}
}
Error codes:
400: Bad Request (Your inputs are wrong/impossible)
404: Not Found
POST /api/branding
Create a submission on a video. If a duplicate submission exists, it votes on that submission.
If you're looking to automate submissions: please see the Automating Submissions page.
Input (JSON Body):
{
videoID: string,
userID: string, // This should be a randomly generated UUID stored locally (not the public one)
userAgent: string, // "Name of Client/Version" or "[BOT] Name of Bot/Version" ex. "Chromium/1.0.0"
service: string, // Optional, default is 'YouTube'. [1]
title: { // Optional, you can submit either just a title, or just a thumbnail, or both
title: string,
},
thumbnail: {
timestamp: number, // Optional if original is true
original: boolean
},
downvote: boolean, // Optional, setting to true downvotes instead of upvoting, will error if the submissions don't exist
autoLock: boolean, // Optional, applies to VIPs only, default true, set to false to vote as a regular user
}
References: [1]
Error codes:
400: Bad Request (Your inputs are wrong/impossible)
500: Internal Server Error (you tried to downvote a submission that doesn't exist)
Generating a thumbnail from a timestamp
Generating thumbnails is handled by a different service. This service will generate thumbnails, and cache them for future users. It is not guaranteed to return, and uses a queuing system. The browser extension uses a fallback local rendering system to handle this, and will render it locally when the server is not able to. It does this by taking a screenshot a video element.
This service is state-less, so can easily be self-hosted without having to sync submissions from the main server.
The main instance is hosted at https://dearrow-thumb.ajay.app
The basic endpoint is as follows
GET /api/v1/getThumbnail
Get submissions for a video.
Input (URL Parameters):
{
videoID: string,
time: number
}
References: [1]
Response:
A binary image response.
Response codes (PLEASE READ):
200: Ok
204: No content, failed to generate, or chose not to generate (reason in X-Failure-Reason
header)
Speeding up requests
You can speed up requests by making a request to getThumbnail
at the same time as a request to branding, but without providing a value in the time
field. The server will respond with an image if it has one. Once both requests are done, you then have to make sure the thumbnail is for the correct timestamps.
You need to check the X-Timestamp
header and verify it is the same as the branding response. If it is not, then you must make a second request with the new time.
There also is a X-Title
header that is used by the extension as a fallback in the result that the main server goes down.