diff --git a/.github/workflows/container-release.yml b/.github/workflows/container-release.yml new file mode 100644 index 0000000..31cbe49 --- /dev/null +++ b/.github/workflows/container-release.yml @@ -0,0 +1,35 @@ +--- +name: Build and release container + +on: + push: + branches: + - "master" + +jobs: + release: + + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to registry + uses: docker/login-action@v1 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_PASSWORD }} + + - name: Build and push + uses: docker/build-push-action@v2 + with: + push: true + tags: quay.io/invidious/docs.invidious.io:latest diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8ab683f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM squidfunk/mkdocs-material:latest as build +WORKDIR /build +COPY . . +RUN mkdocs build + +FROM docker.io/library/nginx:alpine +COPY --from=build /build/site/ /usr/share/nginx/html/ diff --git a/site/404.html b/site/404.html deleted file mode 100644 index a1445dc..0000000 --- a/site/404.html +++ /dev/null @@ -1,579 +0,0 @@ - - - -
- - - - - - - - - - - - - - - -All endpoints that return a JSON body support &hl=LANGUAGE
for translating fields into the desired language. A list of languages are provided in List of URL parameters.
All endpoints that return a JSON body support &pretty=1
for printing the response as formatted JSON.
All endpoints that return a JSON body support the fields API for specifying desired fields to reduce bandwidth consumption. This can be used by adding &fields=FIELDS
with the desired fields, for example /api/v1/videos/aqz-KE-bpKQ?fields=videoId,title,description&pretty=1
.
/api/v1/stats
--Schema:
-
{
- "version": String,
- "software": {
- "name": "invidious",
- "version": String,
- "branch": String
- },
- "openRegistrations": Bool,
- "usage": {
- "users": {
- "total": Int32,
- "activeHalfyear": Int32,
- "activeMonth": Int32
- }
- },
- "metadata": {
- "updatedAt": Int64,
- "lastChannelRefreshedAt": Int64
- }
-}
-
-/api/v1/videos/:id
--Schema:
-
{
- "title": String,
- "videoId": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
-
- "description": String,
- "descriptionHtml": String,
- "published": Int64,
- "publishedText": String,
-
- "keywords": Array(String),
- "viewCount": Int64,
- "likeCount": Int32,
- "dislikeCount": Int32,
-
- "paid": Bool,
- "premium": Bool,
- "isFamilyFriendly": Bool,
- "allowedRegions": Array(String),
- "genre": String,
- "genreUrl": String,
-
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "authorThumbnails": [
- {
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
-
- "subCountText": String,
- "lengthSeconds": Int32,
- "allowRatings": Bool,
- "rating": Float32,
- "isListed": Bool,
- "liveNow": Bool,
- "isUpcoming": Bool,
- "premiereTimestamp": Int64?,
-
- "hlsUrl": String?,
- "adaptiveFormats": [
- {
- "index": String,
- "bitrate": String,
- "init": String,
- "url": String,
- "itag": String,
- "type": String,
- "clen": String,
- "lmt": String,
- "projectionType": Int32,
- "container": String,
- "encoding": String,
- "qualityLabel": String?,
- "resolution": String?
- }
- ],
- "formatStreams": [
- {
- "url": String,
- "itag": String,
- "type": String,
- "quality": String,
- "container": String,
- "encoding": String,
- "qualityLabel": String,
- "resolution": String,
- "size": String
- }
- ],
- "captions": [
- {
- "label": String,
- "languageCode": String,
- "url": String
- }
- ],
- "recommendedVideos": [
- {
- "videoId": String,
- "title": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
- "author": String,
- "lengthSeconds": Int32,
- "viewCountText": String
- }
- ]
-}
-
-Parameters:
-region: ISO 3166 country code (default: "US")
-
-/api/v1/annotations/:id
Parameters:
-source: "archive", "youtube" (default: "archive")
-
-Returns annotation XML from YouTube's /annotations_invideo
endpoint. Alternatively it provides access to legacy annotation data using this collection on archive.org.
/api/v1/comments/:id
--Schema:
-
{
- "commentCount": Int32?,
- "videoId": String,
- "comments": [
- {
- "author": String,
- "authorThumbnails": [
- {
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
- "authorId": String,
- "authorUrl": String,
- "isEdited": Bool,
- "content": String,
- "contentHtml": String,
- "published": Int64,
- "publishedText": String,
- "likeCount": Int32,
- "commentId": String,
- "authorIsChannelOwner": Bool,
- "creatorHeart": {
- "creatorThumbnail": String,
- "creatorName": String
- }?,
- "replies": {
- "replyCount": Int32,
- "continuation": String
- }?
- }
- ],
- "continuation": String?
-}
-
-Parameters:
-sort_by: "top", "new" (default: top)
-source: "youtube", "reddit" (default: youtube)
-continuation: String
-
-/api/v1/captions/:id
--Schema:
-
{
- "captions": [
- {
- "label": String,
- "languageCode": String,
- "url": String
- }
- ]
-}
-
-Parameters:
-label: String
-lang: String
-tlang: String
-region: ISO 3166 country code (default: "US")
-
-A request with label
will return the selected captions in WebVTT format.
-Captions can also be selected with an ISO lang
, e.g. &lang=en, tlang
will auto-translate from English into the requested language (if English captions are available).
/api/v1/trending
--Schema:
-
[
- {
- "title": String,
- "videoId": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
-
- "lengthSeconds": Int32,
- "viewCount": Int64,
-
- "author": String,
- "authorId": String,
- "authorUrl": String,
-
- "published": Int64,
- "publishedText": String,
- "description": String,
- "descriptionHtml": String,
-
- "liveNow": Bool,
- "paid": Bool,
- "premium": Bool
- }
-]
-
-Parameters:
-type: "music", "gaming", "news", "movies"
-region: ISO 3166 country code (default: "US")
-
-/api/v1/popular
--Schema:
-
[
- {
- "type": "shortVideo",
- "title": String,
- "videoId": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
-
- "lengthSeconds": Int32,
- "viewCount": Int64,
-
- "author": String,
- "authorId": String,
- "authorUrl": String,
-
- "published": Int64,
- "publishedText": String
- }
-]
-
-/api/v1/channels/:ucid
--Schema:
-
{
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "authorBanners": [
- {
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
- "authorThumbnails": [
- {
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
-
- "subCount": Int32,
- "totalViews": Int64,
- "joined": Int64,
-
- "paid": Bool,
- "autoGenerated": Bool,
- "isFamilyFriendly": Bool,
- "description": String,
- "descriptionHtml": String,
- "allowedRegions": Array(String),
-
- "latestVideos": [
- {
- "title": String,
- "videoId": String,
- "author": String,
- "authorId": String,
- "authorUrl": String,
-
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
- "description": String,
- "descriptionHtml": String,
- "viewCount": Int64,
- "published": Int64,
- "publishedText": String,
- "lengthSeconds": Int32,
- "paid": Bool,
- "premium": Bool
- }
- ],
- "relatedChannels": [
- {
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "authorThumbnails": [
- {
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ]
- }
- ]
-}
-
-Parameters:
-sort_by: "newest", "oldest", "popular" (default: newest)
-
-Note that a channel's username (if it doesn't include spaces) is also valid in place of ucid
, e.g. /api/v1/channels/BlenderFoundation
.
/api/v1/channels/:ucid/videos
, /api/v1/channels/videos/:ucid
--Schema:
-
[
- {
- title: String,
- videoId: String,
- author: String,
- authorId: String,
- authorUrl: String,
-
- videoThumbnails: [
- {
- quality: String,
- url: String,
- width: Int32,
- height: Int32
- }
- ],
- description: String,
- descriptionHtml: String,
-
- viewCount: Int64,
- published: Int64,
- publishedText: String,
- lengthSeconds: Int32
- paid: Bool,
- premium: Bool
- }
-]
-
-Parameters:
-page: Int32
-sort_by: "newest", "oldest", "popular" (default: newest)
-
-/api/v1/channels/:ucid/latest
, /api/v1/channels/latest/:ucid
[
- {
- title: String,
- videoId: String,
- authorId: String,
- authorUrl: String,
-
- videoThumbnails: [
- {
- quality: String,
- url: String,
- width: Int32,
- height: Int32
- }
- ],
- description: String,
- descriptionHtml: String,
-
- viewCount: Int64,
- published: Int64,
- publishedText: String,
- lengthSeconds: Int32
- paid: Bool,
- premium: Bool
- }
-]
-
-/api/v1/channels/playlists/:ucid
, /api/v1/channels/:ucid/playlists
{
- "playlists": [
- {
- "title": String,
- "playlistId": String,
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "videoCount": Int32,
- "videos": [
- {
- "title": String,
- "videoId": String,
- "lengthSeconds": Int32,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ]
- }
- ]
- ],
- "continuation": String?
-}
-
-Parameters:
-continuation: String
-sort_by: "oldest", "newest", "last"
-
-/api/v1/channels/comments/:ucid
, /api/v1/channels/:ucid/comments
{
- "authorId": String,
- "comments": [
- {
- "author": String,
- "authorThumbnails": [
- "url": String,
- "width": Int32,
- "height": Int32
- ],
- "authorId": String,
- "authorUrl": String,
- "isEdited": Bool,
- "content": String,
- "contentHtml": String,
- "published": Int64,
- "publishedText": String,
- "likeCount": Int32,
- "commentId": String,
- "authorIsChannelOwner": Bool,
- "creatorHeart": {
- "creatorThumbnail": String,
- "creatorName": String
- }?,
- "replies": {
- "replyCount": Int32,
- "continuation": String
- }?,
- "attachment": Attachment?
- }
- ],
- "continuation": String?
-}
-
-The authorId
for top-level comments will always(?) be the same as the requested channel. Top-level comments will also have an optional attachment
, which can be one of:
{
- "type": "image",
- "imageThumbnails": [
- {
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ]
-}
-
-{
- "type": "video",
- "title": String,
- "videoId": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
- "lengthSeconds": Int32,
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "published": Int64,
- "publishedText": String,
- "viewCount": Int64,
- "viewCountText": String
-}
-
-{
- "type": "unknown",
- "error": "Unrecognized attachment type."
-}
-
-Some attachments may only have a type
and error
, similar to the above. Attachments will only be present on top-level comments.
Parameters:
-continuation: String
-
-/api/v1/channels/search/:ucid
--Schema:
-
[
- {
- type: "video",
- title: String,
- videoId: String,
- author: String,
- authorId: String,
- authorUrl: String,
- videoThumbnails: [
- {
- quality: String,
- url: String,
- width: Int32,
- height: Int32
- }
- ],
- description: String,
- descriptionHtml: String,
- viewCount: Int64,
- published: Int64,
- publishedText: String,
- lengthSeconds: Int32,
- liveNow: Bool,
- paid: Bool,
- premium: Bool
- },
- {
- type: "playlist",
- title: String,
- playlistId: String,
- author: String,
- authorId: String,
- authorUrl: String,
-
- videoCount: Int32,
- videos: [
- {
- title: String,
- videoId: String,
- lengthSeconds: Int32,
- videoThumbnails: [
- {
- quality: String,
- url: String,
- width: Int32,
- height: Int32
- }
- ]
- }
- ]
- },
- {
- type: "channel",
- author: String,
- authorId: String,
- authorUrl: String,
-
- authorThumbnails: [
- {
- url: String,
- width: Int32,
- height: Int32
- }
- ],
- subCount: Int32,
- videoCount: Int32,
- description: String,
- descriptionHtml: String
- }
-];
-
-Parameters:
-q: String
-page: Int32
-
-/api/v1/search/suggestions
--Schema:
-
{
- "query": String,
- "suggestions": Array(String)
-}
-
-Parameters:
-q: String
-
-/api/v1/search
--Schema:
-
[
- {
- type: "video",
- title: String,
- videoId: String,
- author: String,
- authorId: String,
- authorUrl: String,
- videoThumbnails: [
- {
- quality: String,
- url: String,
- width: Int32,
- height: Int32
- }
- ],
- description: String,
- descriptionHtml: String,
- viewCount: Int64,
- published: Int64,
- publishedText: String,
- lengthSeconds: Int32,
- liveNow: Bool,
- paid: Bool,
- premium: Bool
- },
- {
- type: "playlist",
- title: String,
- playlistId: String,
- author: String,
- authorId: String,
- authorUrl: String,
-
- videoCount: Int32,
- videos: [
- {
- title: String,
- videoId: String,
- lengthSeconds: Int32,
- videoThumbnails: [
- {
- quality: String,
- url: String,
- width: Int32,
- height: Int32
- }
- ]
- }
- ]
- },
- {
- type: "channel",
- author: String,
- authorId: String,
- authorUrl: String,
-
- authorThumbnails: [
- {
- url: String,
- width: Int32,
- height: Int32
- }
- ],
- subCount: Int32,
- videoCount: Int32,
- description: String,
- descriptionHtml: String
- }
-];
-
-Parameters:
-q: String
-page: Int32
-sort_by: "relevance", "rating", "upload_date", "view_count"
-date: "hour", "today", "week", "month", "year"
-duration: "short", "long"
-type: "video", "playlist", "channel", "all", (default: video)
-features: "hd", "subtitles", "creative_commons", "3d", "live", "purchased", "4k", "360", "location", "hdr" (comma separated: e.g. "&features=hd,subtitles,3d,live")
-region: ISO 3166 country code (default: "US")
-
-/api/v1/playlists/:plid
--Schema:
-
{
- "title": String,
- "playlistId": String,
-
- "author": String,
- "authorId": String,
- "authorThumbnails": [
- {
- "url": String,
- "width": String,
- "height": String
- }
- ],
- "description": String,
- "descriptionHtml": String,
-
- "videoCount": Int32,
- "viewCount": Int64,
- "updated": Int64,
-
- "videos": [
- {
- "title": String,
- "videoId": String,
- "author": String,
- "authorId": String,
- "authorUrl": String,
-
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
- "index": Int32,
- "lengthSeconds": Int32
- }
- ]
-}
-
-Parameters:
-page: Int32
-
-/api/v1/mixes/:rdid
--Schema:
-
{
- title: String,
- mixId: String,
- videos: [
- {
- title: String,
- videoId: String,
- author: String,
- authorId: String,
- authorUrl: String,
- videoThumbnails: [
- {
- quality: String,
- url: String,
- width: Int32,
- height: Int32
- }
- ],
- index: Int32,
- lengthSeconds: Int32
- }
- ]
-}
-
-
-
- Download ViolentMonkey for your Browser: -Firefox -Chrome and Chromium -Others
-Than add the following script in ViolentMonkey. It will always add &local=true
to the end of the video URL.
// ==UserScript==
-// @name Invidious Proxy automatically
-// @match *://*.redirect.invidious.io/watch?v=*
-// @run-at document-start
-// @grant none
-// ==/UserScript==
-
-
-if (!(/[?&]local=/).test(location.search) && !(/[?&]quality=dash/).test(location.search)) {
- location.search += (location.search ? "&" : "?") + "local=true";
-}
-
-You can also enable this by checking Proxy videos?
in your preferences.
ServerName
with your domain.<IfModule mod_ssl.c>
-<VirtualHost *:443>
- ServerName invidious.domain.tld
- ServerAdmin admin@localhost
-
- ProxyPreserveHost On
- ProxyRequests off
- ProxyPass / http://127.0.0.1:3000/
- ProxyPassReverse / http://127.0.0.1:3000/
-
-# ErrorLog /var/log/apache2/invidious.domain.tld/error.log
- CustomLog /dev/null combined
-
-RewriteEngine on
-SSLCertificateFile /etc/letsencrypt/live/invidious.domain.tld/fullchain.pem
-SSLCertificateKeyFile /etc/letsencrypt/live/invidious.domain.tld/privkey.pem
-SSLCertificateChainFile /etc/letsencrypt/live/invidious.domain.tld/chain.pem
-
-</VirtualHost>
-</IfModule>
-
-Listen 3333
to Apache ports.conf
(Debian /etc/apache2/ports.conf
)/etc/systemd/system/invidious.service
) and modify the ExecStart line to include the -b switch as follows ExecStart=/home/invidious/invidious/invidious -b 127.0.0.1 -o invidious.log
and then reload the daemon with systemctl daemon-reload
so that changes are taken into account.<VirtualHost *:3333>
-
- ServerName invidious.domain.tld #add your own domain name (or localhost if you have none)
- ServerAdmin admin@localhost
-
- <Location />
- Deny from all # Forbid access to all by default...
- #Allow from 127.0.0.1 #...Except from specific IPs (which will not need to authenticate)...
- AuthUserFile /etc/apache2/.htpasswd #path to .htpasswd file
- AuthName "Restricted Area" # name displayed in the promptbox
- AuthType Basic # http://httpd.apache.org/docs/current/howto/auth.html
- Satisfy Any
- Require valid-user # ...and except from authenticated users included in the .htpasswd file
- </Location>
-
- ProxyPass / http://127.0.0.1:3000/ nocanon
- ProxyPassReverse / http://127.0.0.1:3000/
- ProxyPreserveHost On
- ProxyRequests Off
- AllowEncodedSlashes On
-
- #ErrorLog ${APACHE_LOG_DIR}/error.log
- CustomLog /dev/null combined
-
-</VirtualHost>
-
-
-
- This is the barebones SSL and non-SSL configs for Apache 2.2 and up. You will need to use Let's Encrypt to generate a certificate. Replace your-domain
with your website. Logs are not recorded by default.
<VirtualHost *:80>
- ServerAdmin webmaster@localhost
- ServerAlias your-domain
-
- ProxyPass / http://0.0.0.0:3000/
- ProxyPassReverse / http://0.0.0.0:3000/
-RemoteIPHeader CF-Connecting-IP
- ErrorLog /dev/null
- CustomLog /dev/null
-RewriteEngine on
-RewriteCond %{SERVER_NAME} =your-domain
-RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
-</VirtualHost>
-
-<VirtualHost *:443>
- ServerAdmin webmaster@localhost
- ServerAlias your-domain
-
- ErrorDocument 503 "Invidious is unavailable at this time."
- ProxyPass / http://0.0.0.0:3000/
- ProxyPassReverse / http://0.0.0.0:3000/
-
- ErrorLog /dev/null
- CustomLog /dev/null
-
-#RemoteIPHeader CF-Connecting-IP
-
-Include /etc/letsencrypt/options-ssl-apache.conf
-ServerName your-domain
-SSLCertificateFile /etc/letsencrypt/live/your-domain/fullchain.pem
-SSLCertificateKeyFile /etc/letsencrypt/live/your-domain/privkey.pem
-</VirtualHost>
-</IfModule>
-
-
-
- All endpoints under namespace /api/v1/auth
require authentication.
Authentication can be in one of two forms:
-Cookie: <SID>
header (for logged in users)Authentication: Bearer <TOKEN>
(recommended)A new token can be generated from /authorize_token
with the given parameters:
scopes: Comma-separated list of scopes
-callback_url: URL to redirect to with generated token
-expire: Int64 how long a given token should be valid (in seconds)
-
-Each scope
has the following format:
METHOD1;METHOD2...:ENDPOINT(*)?
-
-Where METHOD
can be one of GET
, POST
, PUT
, DELETE
, PATCH
.
An ENDPOINT
can be any of the documented endpoints below.
Examples:
-POST:playlists*
: authorizes POST
methods to any endpoint under /api/v1/auth/playlists
(/api/v1/auth/playlists
, /api/v1/playlists/:id/videos
, etc.)
:playlists/*
: authorizes any method to endpoints under /api/v1/auth/playlists/
(/api/v1/auth/playlists/:id
, /api/v1/playlists/:id/videos
, etc.)
GET:playlists/IVPAAAAAAA
: authorizes GET
only to playlist IVPAAAAAAA
.
:preferences
: authorizes any method to /api/v1/auth/preferences
GET;POST:preferences
: authorizes GET
or POST
to /api/v1/auth/preferences
When a callback_url
is specified, after a user has authorized a token with the desired scopes
, a GET request will be made to the callback_url
with the token URL-escaped and appended as token=TOKEN
.
/api/v1/auth/feed
Get subscription feed for the authenticated user.
-Parameters:
-max_results: Int32
-page: Int32
-
---Schema:
-
{
- "notifications": [
- {
- "type": "shortVideo",
- "title": String,
- "videoId": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int64,
- "height": Int64
- }
- ],
- "lengthSeconds": Int64,
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "published": Int64,
- "publishedText": String,
- "viewCount": Int64
- }
- ],
- "videos": [
- {
- "type": "shortVideo",
- "title": String,
- "videoId": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int64,
- "height": Int64
- }
- ],
- "lengthSeconds": Int64,
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "published": Int64,
- "publishedText": String,
- "viewCount": Int64
- }
- ]
-}
-
-/api/v1/auth/notifications
Parameters:
-topics: Array(String) (comma separated: e.g. "UCID1,UCID2) limit of 1000 topics
-since: Int64, timestamp
-
-Provides an EventSource for receiving changes from each topic
in topics
. Currently the only supported topic-type is ucid
, which will return an updated video object whenever the given channel uploads a video.
Important to note is that an event will also be sent when a channel changes an already uploaded video, for example changing description or title.
-Each event is a JSON object with the same schema as /api/v1/videos
. The fields
API can be used, which will be applied to each object.
A debug
topic can also provided which will return a (psuedo-)randomly selected video every minute.
since
will return all videos uploaded since TIMESTAMP
, with a limit of the 15 most recent videos from each topic.
More details in #469.
-/api/v1/auth/notifications
Same as above GET
endpoint, however topics
is moved into post body as Content-Type: application/x-www-form-urlencoded
.
/api/v1/auth/playlists
Get list of playlists for the given user.
---Schema:
-
[
- {
- "type": "invidiousPlaylist",
- "title": String,
- "playlistId": String,
- "author": String,
- "authorId": null,
- "authorUrl": null,
- "authorThumbnails": [],
- "description": String,
- "descriptionHtml": String,
- "videoCount": Int32,
- "viewCount": 0,
- "updated": Int64,
- "isListed": Boolean,
- "videos": [
- {
- "title": String,
- "videoId": String,
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ],
- "index": Int32,
- "indexId": String,
- "lengthSeconds": Int32
- }
- ]
- }
-]
-
-/api/v1/auth/playlists
Content-Type: application/json
Create new playlist.
-Example request body:
-{
- "title": String,
- "privacy": "private"
-}
-
-privacy
can be any of: public
, unlisted
, private
If successful, returns 201, a link to the created resource as a Location
header, and the following response:
{
- "title": String,
- "playlistId": String
-}
-
-/api/v1/auth/playlists/:id
Returns same result as unauthenticated /api/v1/playlists/:id
.
Important to note is that if the requested playlist is marked as private
, it will return an error if the request is not authenticated as the playlist's author.
/api/v1/auth/playlists/:id
Content-Type: application/json
Modify a playlist's description
, title
, description
, or privacy
.
Example request body:
-{
- "title": String,
- "description": String,
- "privacy": "private"
-}
-
-privacy
can be any of: public
, unlisted
, private
Will return 204 on success.
-/api/v1/auth/playlists/:id
Delete a given playlist :id
.
Will return 204 on success.
-/api/v1/auth/playlists/:id/videos
Content-Type: application/json
Add a video to the given playlist :id
.
Example request body:
-{
- "videoId": String
-}
-
-Returns a 201 on success with the following schema:
-{
- "title": String,
- "videoId": String,
- "author": String,
- "authorId": String,
- "authorUrl": String,
- "videoThumbnails": [
- {
- "quality": String,
- "url": String,
- "width": Int32,
- "height": Int32
- }
- ]
-}
-
-/api/v1/auth/playlists/:id/videos/:index
Delete a video from the given playlist :id
with indexId
:index
.
Will return 204 on success.
-/api/v1/auth/preferences
Get preferences for authenticated user.
---Schema:
-
{
- "annotations": false,
- "annotations_subscribed": false,
- "autoplay": false,
- "captions": [
- "",
- "",
- ""
- ],
- "comments": [
- "youtube",
- ""
- ],
- "continue": false,
- "continue_autoplay": true,
- "dark_mode": "light",
- "latest_only": false,
- "listen": false,
- "local": false,
- "locale": "en-US",
- "max_results": 40,
- "notifications_only": false,
- "player_style": "invidious",
- "quality": "hd720",
- "default_home": "Popular",
- "feed_menu": [
- "Trending",
- "Playlists"
- ],
- "related_videos": true,
- "sort": "published",
- "speed": 1.0,
- "thin_mode": false,
- "unseen_only": false,
- "video_loop": false,
- "volume": 100
-}
-
-/api/v1/auth/preferences
Content-Type: application/json
Patch user preferences.
-Example body:
-{
- "speed": 2.0,
- "volume": 10
-}
-
-/api/v1/auth/subscriptions
Get user's subscriptions.
---Schema:
-
[
- {
- "author": String,
- "authorId": String
- }
-]
-
-/api/v1/auth/subscriptions/:ucid
Content-Type: application/json
Add a given ucid
to a user's subscriptions.
Will return 204 on success.
-/api/v1/auth/subscriptions/:ucid
Removes a given ucid
from a user's subscriptions.
Will return 204 on success.
-/api/v1/auth/tokens
Get a list of tokens for the authenticated user.
---Schema:
-
[
- {
- "session": String,
- "issued": Int64
- }
-]
-
-/api/v1/auth/tokens/register
Content-Type: application/json
Create a new token for the authenticated user.
-Example request body:
-{
- "scopes": Array(String), // Each scope has same format as each scope in `/authorize_token`
- "callbackUrl": String?,
- "expire": Int64
-}
-
-Returns a 200 on success with the newly created token as the response body.
-Example response:
-{
- "session":"v1:YUwKEL1XwHQzp7-AAAAAAAAAAAAAAAAAA=",
- "scopes":["GET:notifications"],
- "signature":"jNYdAAAAAAAAAAAAAAAAAAAAAAAAAAAAVAXGb__2Gv-w="
-}
-
-/api/v1/auth/tokens/unregister
Content-Type: application/json
Revoke a token for the authenticated user.
-Example request:
-{
- "session": "v1:YUwKEL1XwHQzp7-AAAAAAAAAAAAAAAAAA="
-}
-
-Returns 204 on success.
- - -The configuration file is located at invidious/config/config.yml.
-channel_threads
(default 1
) Number of threads to use for crawling videos from channels
feed_threads
(default 1
) Number of threads to use for refreshing subscription feeds
db:
- user: kemal # your database user
- password: kemal # your database password
- host: localhost # database host
- port: 5432 # postgres port
-
-full_refresh
(default false
) When crawling channel videos, threads should refresh all videos uploaded by a channel
https_only
(default false
) Used to tell Invidious it is accessed via https, set to true
if you have for example a reverse proxy with a ssl certificate
hmac_key
(default nil
) Signing key for CSRF tokens (when nil
is randomly generated on startup, can be any random string)
domain
(default nil
) Domain to use for providing self
links in RSS feeds, issuing cookies, etc.
use_pubsub_feeds
(default false
) Use server-side notifications provided by YouTube. Requires domain
and hmac_key
to be set
default_home
(default "Popular"
) Default home page Moved into default_user_preferences
feed_menu
(default ["Popular", "Trending", "Subscriptions"]
) Order of tabs on feed menu Moved into default_user_preferences
captcha_enabled
(default true
) Determine if CAPTCHA should be required for registration
login_enabled
(default true
) Whether users should be able to login
registration_enabled
(default true
) Whether new users should be able to register
statistics_enabled
(default false
) Whether statistics should be available from /api/v1/stats
admins
(default []
) List of user IDs that have access to administrator preferences
external_port
(default nil
) Invidious should supply links to a different port (if running behind a proxy, for example). PubSub notifications (if enabled) will also be sent to this port
default_user_preferences
(default ConfigPreferences
) Default preferences to use for new and unregistered users, see #415
dmca_content
(default []
) For compliance with DMCA requests, disables download widget for list of video IDs
check_tables
(default false
) Check table integrity, automatically try to add any missing columns, create columns, etc.
cache_annotations
(default false
) Cache annotations requested from IA, will not cache empty annotations or annotations that only contain cards
banner
(default nil
) Optional banner to be displayed along top of page for announcements, etc.
hsts
(default true
) For HTTP Strict Transport Security
disable_proxy
(default false
) Disable proxy option serverwide (options: 'dash', 'livestreams', 'downloads', 'local')
force_resolve
(default nil
) Force IPv4 or IPv6 connection to Google (options: 'ipv4', 'ipv6') see #811
pool_size
(default 100
) Pool size for HTTP connections for youtube.com and ytimg.com (each domain has a separate pool of pool_size
)
admin_email
(default omarroth@protonmail.com
) Email provided to users for bug reports
port
(default 3000
) Default port for HTTP server
host_binding
(default 0.0.0.0
) Default host for HTTP server
cookies
(default nil
) Cookies to be used when connecting to YouTube
captcha_key
(default nil
) Anti-Captcha API key for solving YouTube CAPTCHAs, see #886.
popular_enabled
(default false
) Whether to display popular videos of the instance.
Invidious needs one PostgreSQL database which has the following tables.
-annotations
Caches annotation data if cache_annotations
is enabled in config.yml
channel_videos
Stores truncated video info, used to create user feedschannels
Stores UCID and author namenonces
Keeps track of tokens issued to prevent CSRFusers
Stores user info, such as preferences, username, subscriptionssession_ids
Keeps track of user sessionsvideos
Stores video cache, used to create "top" pageThe table videos
grows a lot and needs the most storage. You can clean it up using following commands:
$ sudo -i -u postgres
-$ psql invidious -c "DELETE FROM nonces * WHERE expire < current_timestamp"
-$ psql invidious -c "TRUNCATE TABLE videos"
-$ exit
-
-For regular maintenance you should add a cronjob for these commands
-@weekly psql invidious -c "DELETE FROM nonces * WHERE expire < current_timestamp" > /dev/null
-@weekly psql invidious -c "TRUNCATE TABLE videos" > /dev/null
-
-
-
- The steps below as well as the resulting file name are different depending on your Google language -settings.
-Create a new export
choose YouTube and YouTube Music
.All YouTube data included
and only tick subscriptions
in the dialog that opens.Next step
, make sure Export once
is chosen and click on Create export
.Download
under
- Your latest export
that should now be visible.subscriptions.csv
.Import
.Commonly encountered errors
-Could not check out a connection in 2.0 seconds (DB::PoolTimeout)
-Running your own instance
-.deb
, .rpm
, etc..)?<IP>:3000
but I have a reverse proxy!A: As long as your device is equipped with a modern web browser, -sure, of course! A responsive interface is available for mobile/tablets.
-A: No. Invidious is and will always be a browser application.
-If you have an Android phone/tablet, you can check the -NewPipe application.
-A: Invidious by itself does not collect any data about its users, but -keep in mind that instance owners can log your IP address (like any other -server on the internet).
-By default, the server logs which URLs were accessed, the associated error -code (e.g 404 if the URL was not found) and the time it took for the server -to respond.
-Here is what the server logs look like:
-2021-08-30 18:15:44 UTC [info] 200 GET /watch?v=GIAKHj9uJtM 781.21ms
-2021-08-30 18:15:49 UTC [info] 200 GET /api/v1/search?q=Fly%20away 500.0ms
-2021-08-30 18:15:49 UTC [info] 200 GET /vi/lJcqAzWFWLs/mqdefault.jpg 15.82ms
-2021-08-30 18:15:49 UTC [info] 200 GET /vi/JoP_Tte7z7o/mqdefault.jpg 70.64ms
-
-When you create an account, your watch history and the list of channels you -subscribed will be stored in the server's database. You can export, migrate -or delete these data at any time from your user account page.
-A: By default, the video stream is fetched directly from Google's servers
-(googlevideo.com
) in order to reduce the bandwidth required by invidious,
-meaning that Google will be able to see your IP address and some other data
-commonly sent by web browsers, like your user-agent string.
If you don't want that to happen, you can go to the preferences
page and
-check the Proxy videos
option. When this option is enabled, the Invidious
-instance will be used as a relay (also known as a "proxy") between you and
-Google's servers, which will hide your IP address and the other information
-sent by your browser.
A: This problem can occur in different scenarios:
-If you're trying to watch a music clip, Youtube is likely blocking the
- video stream. Try enabling Proxy videos
in the preferences (or add
- &local=1
in the URL). Switching to another instance is also a good
- alternative, as this type of content is often geo-restricted.
Youtube often sends corrupted video data for the hd720
, medium
and
- small
quality settings. Refreshing the page multiple times (5-7) can
- fix the problem. You may also set your preferred video quality
to
- dash
(or add &quality=dash
to the URL).
Rarely, it can be due to an internal failure of the instance and the - video stream can't be fetched. A simple page refresh can solve the issue.
-If none of the solutions listed above fix the problem, try switching -instances. And if that still doesn't work, you'll have to watch the video -on YouTube itself (sorry for the inconvenience).
-A: Please, do not open a bug report on github, we can't do anything!
-The instance you are using is having database issues. Please use another -instance from the list of public instances
-.deb
, .rpm
, etc.)?A: We currently don't provide those, due to the rolling release nature
-of Invidious. Get a fresh clone
or pull
the latest commits from master
-instead.
A: Read the example config file (config/config.example.yml
).
-All the supported configuration options are documented there.
<IP>:3000
but I have a reverse proxy!A: Make sure that the following parameters are set according to your environment:
-- https_only
: if your instance is served over HTTPS
-- domain
: if you have a domain name that redirects to your instance
-- external_port
: if your instance is accessed from a different port than
- the listening one (e.g your instance listens on :3000, but is available on
- :443 through a reverse proxy, set external_port
to 443
)
A: The "popular" feed is generated from the videos that are popular amongst -the users registered on your instance. If nobody has created an account on your -instance (e.g if registration is disabled) the popular feed will be empty.
- - -Sometimes you may notice that you cannot watch a video on Invidious. This is because YouTube is geoblocking, i.e. preventing access to videos based on your geographical location.
-If the Proxy videos?
setting is enabled, Invidious will proxy videos through itself, so the stream will be routed like this:
--YouTube → Invidious/server → Client/browser
-
If a video is blocked where the instance is hosted, then the route would be this:
---YouTube → Proxy server → Invidious/server → Client/browser
-
The current system works by cycling through proxies in different regions, and finding one where the video is not blocked. -The reason geoblocked videos may take a long time to load is because Invidious would have to cycle through all known proxy servers until it finds one that is able to play back the video.
-If the Proxy videos?
setting is disabled, then the stream would be routed like this:
--YouTube → Client/browser
-
On Invidious you often don't have the same quality options as on YouTube. This is because the audio and video streams are separated and Invidious currently can't sync them together.
-DASH is a streaming technique used by YouTube to provide resolutions higher than 720p by providing multiple files for a client to use depending on network and user preferences.
-You can enable DASH by selecting the appropriately named video quality in the settings or by appending &quality=dash
to the end of a video's URL. With this option enabled, the stream is proxied through Invidious for you to then watch at a higher or automatic quality.
If you're using uMatrix, you won't be able to automatically play a video served by Invidious on other websites without unblocking requests to Invidious instances.
-So, to make it work, you'll need to allow css
, image
, media
, script
, xhr
, frame
for the instance from which you're trying to play the video.
Since there are many Invidious instances, you can use the tool called Invimatrix to automatically generate uMatrix rules for every known instance.
- - -Account Key
(never share it, it's confidential).config.yml
file (should be located in the config
directory) and add your account key at the end of the file after the captcha_key
parameter.
-Here is an example:captcha_key: acuGae2riad5quashoug3Leeh
-
-Compiling Invidious requires at least 2GB of free RAM (We recommend to have at least 3GB installed). -If you have less (e.g on a cheap VPS) you can setup a SWAP file or partition, so the combined amount is >= 3GB.
-After installation take a look at the Post-install steps.
-Note: Any PaaS or SaaS provider/software (Heroku, YunoHost, Repli...) are unsupported. Use them at your own risk. They WILL cause problems with Invidious and might even suspend your account for "abuse" since Invidious is heavy, bandwidth intensive and technically a proxy (and most providers don't like them). If you use one and want to report an issue, please mention which one you use.
-Invidious-Updater is a self-contained script that can automatically install and update Invidious.
---The Invidious docker image is only available on Quay because, unlike Docker Hub, Quay is Free and Open Source Software. This is reflected in the
-docker-compose.yml
file used in this walk-through.{.is-warning}
Ensure Docker Engine and Docker Compose are installed before beginning.
-This method uses the pre-built Docker image from quay
-Note: Currently the repository has to be cloned, this is because the init-invidious-db.sh
file and the config/sql
directory have to be mounted to the postgres container (See the volumes section in the docker-compose file below). This "problem" will be solved in the future.
git clone https://github.com/iv-org/invidious.git
-cd invidious
-
-Edit the docker-compose.yml with this content:
-version: "3"
-services:
-
- invidious:
- image: quay.io/invidious/invidious:latest
- # image: quay.io/invidious/invidious:latest-arm64 # ARM64/AArch64 devices
- restart: unless-stopped
- ports:
- - "127.0.0.1:3000:3000"
- environment:
- # Please read the following file for a comprehensive list of all available
- # configuration options and their associated syntax:
- # https://github.com/iv-org/invidious/blob/master/config/config.example.yml
- INVIDIOUS_CONFIG: |
- db:
- dbname: invidious
- user: kemal
- password: kemal
- host: invidious-db
- port: 5432
- check_tables: true
- # external_port:
- # domain:
- # https_only: false
- # statistics_enabled: false
- healthcheck:
- test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/comments/jNQXAC9IVRw || exit 1
- interval: 30s
- timeout: 5s
- retries: 2
- depends_on:
- - invidious-db
-
- invidious-db:
- image: docker.io/library/postgres:14
- restart: unless-stopped
- volumes:
- - postgresdata:/var/lib/postgresql/data
- - ./config/sql:/config/sql
- - ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
- environment:
- POSTGRES_DB: invidious
- POSTGRES_USER: kemal
- POSTGRES_PASSWORD: kemal
- healthcheck:
- test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
-
-volumes:
- postgresdata:
-
-Note: This compose is made for a true "production" setup, where Invidious is behind a reverse proxy. If you prefer to directly access Invidious, replace 127.0.0.1:3000:3000
with 3000:3000
under the ports:
section.
--The environment variable
-POSTGRES_USER
cannot be changed. The SQL config files that run the initial database migrations are hard-coded with the usernamekemal
. -{.is-warning}
This method builds a Docker image from source
-git clone https://github.com/iv-org/invidious.git
-cd invidious
-docker-compose up
-
-Follow the instructions for your distribution here: https://crystal-lang.org/install/
-Arch Linux
-sudo pacman -S base-devel librsvg postgresql
-
-Debian/Ubuntu
-sudo apt install libssl-dev libxml2-dev libyaml-dev libgmp-dev libreadline-dev postgresql librsvg2-bin libsqlite3-dev zlib1g-dev libpcre3-dev libevent-dev
-
-RHEL based and RHEL-like systems (RHEL, Fedora, AlmaLinux, RockyLinux...)
-sudo dnf install -y openssl-devel libevent-devel libxml2-devel libyaml-devel gmp-devel readline-devel postgresql librsvg2-devel sqlite-devel zlib-devel gcc
-
-useradd -m invidious
-su - invidious
-git clone https://github.com/iv-org/invidious
-exit
-
-systemctl enable --now postgresql
-sudo -i -u postgres
-psql -c "CREATE USER kemal WITH PASSWORD 'kemal';" # Change 'kemal' here to a stronger password, and update `password` in config/config.yml
-createdb -O kemal invidious
-psql invidious kemal < /home/invidious/invidious/config/sql/channels.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/videos.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/channel_videos.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/users.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/session_ids.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/nonces.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/annotations.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/playlists.sql
-psql invidious kemal < /home/invidious/invidious/config/sql/playlist_videos.sql
-exit
-
-su - invidious
-cd invidious
-shards install --production
-crystal build src/invidious.cr --release
-exit
-
-cp /home/invidious/invidious/invidious.service /etc/systemd/system/invidious.service
-systemctl enable --now invidious.service
-
-# Install dependencies
-brew update
-brew install shards crystal postgres imagemagick librsvg
-
-# Clone the repository and set up a PostgreSQL database
-git clone https://github.com/iv-org/invidious
-cd invidious
-brew services start postgresql
-psql -c "CREATE ROLE kemal WITH PASSWORD 'kemal';" # Change 'kemal' here to a stronger password, and update `password` in config/config.yml
-createdb -O kemal invidious
-psql invidious kemal < config/sql/channels.sql
-psql invidious kemal < config/sql/videos.sql
-psql invidious kemal < config/sql/channel_videos.sql
-psql invidious kemal < config/sql/users.sql
-psql invidious kemal < config/sql/session_ids.sql
-psql invidious kemal < config/sql/nonces.sql
-psql invidious kemal < config/sql/annotations.sql
-psql invidious kemal < config/sql/privacy.sql
-psql invidious kemal < config/sql/playlists.sql
-psql invidious kemal < config/sql/playlist_videos.sql
-
-# Set up Invidious
-shards update && shards install && crystal build src/invidious.cr --release
-
-Detailed configuration available in the configuration guide.
-Because of various issues Invidious must be restarted often, at least once a day, ideally every hour.
-If you use a reverse proxy, you must configure invidious to properly serve request through it:
-https_only: true
: if you are serving your instance via https, set it to true
domain: domain.ext
: if you are serving your instance via a domain name, set it here
external_port: 443
: if you are serving your instance via https, set it to 443
docker-compose pull && docker-compose up && docker image prune -f
-
-sudo - invidious
-cd invidious
-shards update && shards install && crystal build src/invidious.cr --release
-exit
-systemctl restart invidious.service
-
-./invidious
-
-echo "/home/invidious/invidious/invidious.log {
-rotate 4
-weekly
-notifempty
-missingok
-compress
-minsize 1048576
-}" | tee /etc/logrotate.d/invidious.logrotate
-chmod 0644 /etc/logrotate.d/invidious.logrotate
-
-
-
- Uptime History provided by Uptimerobot
- -Warning: Any public instance that isn't in this list is considered untrustworthy. Use them at your own risk.
-yewtu.be 🇳🇱 - Source code/changes: https://github.com/unixfox/invidious-custom
-invidious.kavin.rocks 🇮🇳 invidious-us.kavin.rocks 🇺🇸 (uses Cloudflare)
-youtube.076.ne.jp 🇯🇵 - Source code/changes: https://git.076.ne.jp/TechnicalSuwako/invidious-mod
-tube.cthd.icu 🇷🇸 - Source code/changes: https://gitlab.cthd.icu/cthd/invidious-custom
-c7hqkpkpemu6e7emz5b4vyz7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion 🇫🇮 (Onion of invidious.snopyta.org)
-w6ijuptxiku4xpnnaetxvnkc5vqcdu7mgns2u77qefoixi63vbvnpnqd.onion
-kbjggqkzv65ivcqj6bumvp337z6264huv5kpkwuv6gu5yjiskvan7fad.onion 🇳🇱
-grwp24hodrefzvjjuccrkw3mjq4tzhaaq32amf33dzpmuxe7ilepcmad.onion 🇺🇸 (Onion of vid.puffyan.us)
-hpniueoejy4opn7bc4ftgazyqjoeqwlvh2uiku2xqku6zpoa4bf5ruid.onion 🇺🇸 (Onion of invidious-us.kavin.rocks)
-osbivz6guyeahrwp2lnwyjk2xos342h4ocsxyqrlaopqjuhwn2djiiyd.onion 🇳🇱 (Onion of invidious.hub.ne.kr)
-u2cvlit75owumwpy4dj2hsmvkq7nvrclkpht7xgyye2pyoxhpmclkrad.onion 🇺🇸 (Onion of inv.riverside.rocks)
-2rorw2w54tr7jkasn53l5swbjnbvz3ubebhswscnc54yac6gmkxaeeqd.onion 🇺🇸 (Onion of invidious.privacy.gd)
-statistics_enabled:true
in the configuration file).NOTE: We reserve the right to decline any instance from being added to the list, and to remove or ban any instance that repeatedly breaks the aforementioned rules.
- - -There is some issue on Debian 9 and Ubuntu 18.04 and later. It appears that the clock (the CAPTCHA) has no hands but you can see them outside the clock. You need to compile ImageMagick yourself with librsvg to solve this issue. -Thanks Tmiland for showing us a solution at #299
-For lazy people, a little hack is to disable CAPTCHA or use text one.
-You can check if your version of ImageMagick is affected with convert -list format
.
-It should show the following if your installed version is okay.
SVG SVG rw+ Scalable Vector Graphics (RSVG 2.40.13)
- SVGZ SVG rw+ Compressed Scalable Vector Graphics (RSVG 2.40.13)
-
-If this is not the case, your version is not compiled with librsvg, then you get the following.
- SVG SVG rw+ Scalable Vector Graphics (XML 2.9.4)
- SVGZ SVG rw+ Compressed Scalable Vector Graphics (XML 2.9.4)
-
-Follow the steps to fix this issue:
-$ sudo apt purge imagemagick
-$ cd /tmp
-# check for new releases: https://github.com/ImageMagick/ImageMagick6/releases
-$ wget https://github.com/ImageMagick/ImageMagick6/archive/6.9.11-19.tar.gz
-$ tar -xvf 6.9.10-24.tar.gz
-$ cd ImageMagick6-6.9.10-24
-$ ./configure --with-rsvg
-$ make
-$ sudo make install
-
-Set the correct path: $ sudo ln -s /usr/local/bin/convert /usr/bin/convert
-If you get an error here that this file already exists, please execute $ sudo apt autoremove
Now convert -list format
reports
SVG rw+ Scalable Vector Graphics (RSVG 2.40.16)
- SVGZ rw+ Compressed Scalable Vector Graphics (RSVG 2.40.16)
-
-Restart Invidious, just to be sure:
-$ sudo systemctl restart invidious.service
-
-
-
- In this wiki page some known exceptions from the logfile are listed. You normally do not have to worry if you see them.
-"Connection reset by peer" means the client disconnected before the site finished loading
-A list of URL parameters for Invidious, which can automatically toggle various UI and player settings.
-This list is incomplete. You can help by expanding it.
-Parameter | -Setting | -
---|---|
Site-wide parameters | -- |
Dark mode | -Configure default theme without setting cookies | -
dark_mode=true |
-Use dark theme | -
dark_mode=false |
-Use light theme | -
Thin mode | -Load HTML, CSS, JS and video elements (disables images) | -
thin_mode=true |
-Enabled | -
thin_mode=false |
-Disabled | -
UI Language | -Available locales are also listed here | -
hl=ar |
-Arabic | -
hl=de |
-German | -
hl=el |
-Greek | -
hl=en-US |
-English | -
hl=eo |
-Esperanto | -
hl=es |
-Spanish | -
hl=eu |
-Basque | -
hl=fr |
-French | -
hl=is |
-Icelandic | -
hl=it |
-Italian | -
hl=nb_NO |
-Norwegian Bokmål | -
hl=nl |
-Dutch | -
hl=pl |
-Polish | -
hl=ru |
-Russian | -
hl=uk |
-Ukranian | -
hl=zh-CN |
-Chinese (traditional) | -
Player parameters | -Available parameters also listed here | -
Annotations | -Show legacy annotations, provided by the Internet Archive | -
iv_load_policy=1 |
-Show annotations | -
iv_load_policy=3 |
-Hide annotations | -
Autoplay | -Automatically play video on load | -
autoplay=1 |
-Enabled | -
autoplay=0 |
-Disabled | -
Continue | -When video is done, automatically go to the next related video (similar to YouTube’s Autoplay feature) | -
continue=1 |
-Enabled | -
continue=0 |
-Disabled | -
Listen | -Play only audio portion of video | -
listen=true |
-Enabled | -
listen=false |
-Disabled | -
Local | -Proxy video streams, equivalent to enabling Proxy videos? in preferences |
-
local=true |
-Enabled | -
local=false |
-Disabled | -
Subtitles | -List of ISO 639-1 language codes (comma-separated) | -
subtitles=en |
-English (will use auto-generated if native translation is unavailable) |
-
Quality | -Default player quality | -
quality=dash |
-DASH | -
quality=hd720 |
-720p | -
quality=medium |
-480p | -
Related Videos | -Show "Related videos" tab on the right-hand side | -
related_videos=false |
-Disabled | -
Speed | -Default player speed, can be any positive number | -
speed=0.5 |
-Play at 0.5x speed | -
speed=2 |
-Play at 2x speed | -
speed=9.34 |
-Play at 9.34x speed | -
Loop | -Loop player by default | -
loop=1 |
-Enabled | -
loop=0 |
-Disabled | -
Volume | -Default player volume, can be any whole number between 0 and 100 | -
volume=10 |
-Play video at 10% volume | -
Region | -Provide "hint" (as ISO 3166 country code) for Invidious to load videos from the specified region | -
region=JP |
-Attempt to load video as if the user were in Japan | -
region=DE |
-Attempt to load video as if the user were in Germany | -
Controls | -Provide player controls | -
controls=1 |
-Enabled | -
controls=0 |
-Disabled | -
Raw | -Redirect to latest copy of video at the specified quality and optionally proxy video |
-
raw=1 |
-Enabled | -
raw=0 |
-Disabled | -
Time controls | -Control when the player starts and stops playback. Providing loop=1 will only loop the specified section |
-
start=TIME , t=TIME , time_continue=TIME |
-Start playback at TIME seconds into the video. Supports TIME as either an integer specifying seconds or using 12h30m10s22ms syntax. For example, t=12m9s is equivalent to t=729 |
-
end=TIME |
-Stop playback at either TIME seconds or using the above mentioned 12h56m10s22ms syntax. |
-
Search parameters | -- |
Region | -Provide "hint" (as ISO 3166 country code) for Invidious to load search results from the specified region | -
region=JP |
-Attempt to load search results as if the user were in Japan | -
region=DE |
-Attempt to load search results as if the user were in Germany | -
Trending parameters | -- |
Trending type | -View trending videos only in a specific category | -
type=Default |
-Default | -
type=Music |
-Music | -
type=Gaming |
-Gaming | -
type=News |
-News | -
type=Movies |
-Movies | -
Region | -Provide "hint" (as ISO 3166 country code) for Invidious to load trending videos from the specified region | -
region=JP |
-Load videos that are trending in Japan | -
region=DE |
-Load videos that are trending in Germany | -
Player Style | -- |
player_style=invidious |
-Invidious, the default | -
player_style=youtube |
-YouTube, using a centered play button and always visible video control bar | -
This is a very basic config, secured with Let's Encrypt. Any log is disabled by default. Do not forget to replace server_name
with your domain.
server {
- listen 80;
- listen [::]:80;
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
-
- server_name invidious.domain.tld;
-
- access_log off;
- error_log /var/log/nginx/error.log crit;
-
- ssl_certificate /etc/letsencrypt/live/invidious.domain.tld/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/invidious.domain.tld/privkey.pem;
-
- location / {
- proxy_pass http://127.0.0.1:3000/;
- proxy_set_header X-Forwarded-For $remote_addr;
- proxy_set_header Host $host; # so Invidious knows domain
- proxy_http_version 1.1; # to keep alive
- proxy_set_header Connection ""; # to keep alive
- }
-
- if ($https = '') { return 301 https://$host$request_uri; } # if not connected to HTTPS, perma-redirect to HTTPS
-}
-
-
-
- Preferences for Invidious can be stored in a cookie named PREFS
. This cookie can be set on the Invidious Preferences page.
If setting the cookie value yourself, the value must be in JSON format and then URL-encoded.
-These are the preferences you can set:
-{
- "video_loop":true, // Always loop
- "annotations":true, // Show annotations
- "annotations_subscribed":true, // Show annotations for subscribed channels
- "autoplay":true, // Autoplay current video
- "continue":true, // Load next video when current video finishes
- "continue_autoplay":true, // Load and autoplay next video
- "listen":true, // Audio-only mode by default
- "local": true, // Proxy requests via Invidious instance for privacy
- "speed":1.0, // Also accepts '0.5', '1.5', '2.0'
- "quality":"hd720", // Also accepts 'dash' for 1080p, 'medium', 'small'
- "volume":100, // Default audio volume (0 = Min, 100 = Max)
- "comments":[ // Source to use for comments; 'youtube' or 'reddit'
- "youtube",
- ""
- ],
- "captions":[ // Language captions in order of preference
- "",
- "",
- ""
- ],
- "related_videos":true, // Show related videos
- "redirect_feed":true, // Redirect homepage to subscription feed
- "locale":"en-US", // Choose interface language
- "dark_mode":true, // Use dark mode
- "thin_mode":true, // Don't include pictures in page load
- "player_style":"invidious", // Invidious style, the default
- "player_style":"youtube", // YouTube style, using a centered play button and always visible video control bar
-
-
- // For registered users (currently unused):
- "max_results":40,
- "sort":"published",
- "latest_only":false,
- "unseen_only":false,
- "notifications_only":false
-}
-
-
-
- Invidious supports the various search filters provided by YouTube.
-Support for more user-friendly search is planned, see #179.
-Search filters are currently implemented as key:value
operators, similar to DuckDuckGo and other search engines. Operators can be added to the search query to filter results, for example: type:playlist sort:views music
.
When using subscriptions:true
or channel:UCxxx
other filters are not applied.
Supported operators:
-sort:
relevance
(default)rating
upload_date
, date
view_count
, views
date:
hour
today
week
month
year
type:
all
(default)video
channel
playlist
movie
show
duration:
short
long
features:
Multiple can be specified, for example features:live,4k,subtitles
hd
subtitles
creative_commons
,cc
live
, livestream
purchased
4k
360
location
hdr
channel:
, user:
UCxxxxxxxxxxxxxxxxxxxxxx
author
Can be ambiguous, so using UCID
is recommendedsubscriptions:
If logged in, search only for videos from subscribed channelstrue
false
While running Invidious, it is very possible you will recive a DMCA at some point. A copyright agent will probably at some point search the ID of an infringing video on a search engine and see an Invidious instance appear. At least in the United States, Invidious instances should in theory be immune to DMCA laws because of 17 U.S. Code § 512 stating that a provider is not responsible for content assuming that "the material is transmitted through the system or network without modification of its content."
-Hello,
-
-I am writing on behalf of {{website}}. I am the webmaster of {{website}} and all of its subdomains.
-
-I see you are filing a claim for {{invidious instance url}}. {{invidious instance url}} hosts Invidious, a private YouTube front-end, meaning it is simply a proxy to access YouTube assets and user generated content without tracking from Google. Thus, all content is proxied from YouTube and is not stored on our servers and if YouTube chooses to remove an asset, it will no longer appear on our site.
-
-Our {{server hosting}} {{invidious instance url}} is hosted in the United States, so the United States's laws apply. Under United States copyright law 17 U.S.C. § 512(a), part of the Digital Millennium Copyright Act, we cannot be liable for content that "is transmitted through the system or network without modification of its content."
-
-As such, all takedown requests must be sent to YouTube, as we don't have any control on the data that they have on their servers.
-
-Thank you,
-{{name}}
-
-Hello,
-
-I am writing on behalf of {{website}}. I am the webmaster of {{website}} and all of its subdomains.
-
-I see you are filing a claim for {{invidious instance url}}. {{invidious instance url}} hosts Invidious, a private YouTube front-end, meaning it is simply a proxy to access YouTube assets and user generated content without tracking from Google. Thus, all content is proxied from YouTube and is not stored on our servers and if YouTube chooses to remove an asset, it will no longer appear on our site.
-
-Our {{server hosting}} {{invidious instance url}} is hosted in the European Union, so the European Union's laws apply. Under the directive 2001/29/EC of the European Parliament and of the Council of 22 May 2001 on the harmonization of certain aspects of copyright and related rights in the information society, "temporary acts of reproduction referred to in Article 2, which are transient or incidental [and] an integral and essential part of a technological process and whose sole purpose is to enable: a transmission in a network between third parties by an intermediary" is allowed, and legal.
-
-As such, all takedown requests must be sent to YouTube, as we don't have any control on the data that they have on their servers.
-
-Thank you,
-{{name}}
-
-
-
- \n {translation(\"search.result.term.missing\")}: {...missing}\n
\n }\n