Skip to main content

YouTube

SimplePost uploads videos to YouTube through the YouTube Data API v3. YouTube access is tied to a Google account and channel, so authenticate as the channel owner or a Brand Account manager.

Content support

CapabilitySupport
MediaVideos only.
TitleRequired. Up to 100 characters.
DescriptionOptional. Up to 5000 characters.
Optional fieldstags, categoryId, playlistId, thumbnailPath, thumbnailUrl, selfDeclaredMadeForKids.
Scheduler thumbnailUpload a JPG/PNG custom thumbnail in the YouTube per-account options, or pass accountOptions[accountId].thumbnailUrl through the Scheduler API.
ShortsUse a normal upload; YouTube classifies Shorts based on duration and aspect ratio.
Native schedulingpublishAt option (ISO 8601 timestamp).

When publishAt is set, SimplePost posts the video as private regardless of the supplied privacyStatus and lets YouTube flip it public at the scheduled time.

Set up credentials

The fastest path is the CLI bundled OAuth client (simplepost account add youtube) or the Scheduler app. Use the steps below only when you want to drive the SDK directly with your own Google project.

1. Create or select a Google Cloud project

Open the Google Cloud Console and create or select a project dedicated to SimplePost.

2. Enable YouTube Data API v3

Open APIs & Services, find YouTube Data API v3, and enable it.

Configure the OAuth consent screen. Add upload scopes:

https://www.googleapis.com/auth/youtube.upload
https://www.googleapis.com/auth/youtube

Add yourself as a test user while the app is in testing mode.

4. Create OAuth client credentials

Create OAuth 2.0 Client ID credentials with application type Web application. Add the redirect URI used by your app or Scheduler deployment.

For local manual testing, a redirect URI like this is common:

http://localhost:3000/youtube

Save the Client ID and Client Secret.

5. Generate tokens

Run an OAuth authorization flow with access_type=offline and prompt=consent so Google returns a refresh token. Store the refresh token for long-lived uploads.

Environment variables

YOUTUBE_CLIENT_ID=
YOUTUBE_CLIENT_SECRET=
YOUTUBE_REFRESH_TOKEN=

All three variables must be set together. The shorter accessToken-only credential variant is supported through options.youtube.credentials.accessToken but not through env vars.

SDK options

await post({
content: {
media: [
{
type: "video",
path: "./video.mp4",
title: "Launch demo",
description: "A short demo",
},
],
},
platforms: ["youtube"],
options: {
youtube: {
privacyStatus: "unlisted",
tags: ["demo", "launch"],
categoryId: "22",
playlistId: "PL1234567890",
thumbnailPath: "./thumbnail.jpg",
selfDeclaredMadeForKids: false,
publishAt: "2030-01-01T12:00:00Z",
},
},
});

Common category IDs:

IDCategory
10Music
20Gaming
22People & Blogs
23Comedy
24Entertainment
25News & Politics
26Howto & Style
27Education
28Science & Technology

Custom thumbnails can be supplied either on the video media item or in options.youtube. The YouTube option takes precedence:

await post({
content: {
media: [{ type: "video", path: "./video.mp4", title: "Launch demo" }],
},
platforms: ["youtube"],
options: {
youtube: {
thumbnailPath: "./thumbnail.jpg",
// or thumbnailUrl: "https://cdn.example.com/thumbnail.jpg"
},
},
});

For Scheduler API calls, upload the thumbnail first, then set the returned public URL in per-account options:

{
"accountOptions": {
"youtube-account-id": {
"thumbnailUrl": "https://cdn.example.com/thumbnail.jpg"
}
}
}

REST server account

Add this entry under accounts in the self-hosted REST server's accounts.json:

{
"id": "youtube-main",
"platform": "youtube",
"credentials": {
"clientId": "...",
"clientSecret": "...",
"refreshToken": "..."
},
"options": {
"privacyStatus": "public",
"categoryId": "22",
"thumbnailUrl": "https://cdn.example.com/thumbnail.jpg"
}
}