diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..437072cf --- /dev/null +++ b/404.html @@ -0,0 +1,568 @@ + + + + + + + + + + + + + + + + + + + + Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/CHANGELOG/index.html b/CHANGELOG/index.html new file mode 100644 index 00000000..58c85265 --- /dev/null +++ b/CHANGELOG/index.html @@ -0,0 +1,1440 @@ + + + + + + + + + + + + + + + + + + + + + + + + Changelog - Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Changelog

+

All notable changes to this project will be documented in this file.

+

Version 0.9.4 (2024-02-18)

+

What's New

+
    +
  • Add new parameter for_handle to get channel by handle.
  • +
  • fix some wrong error message.
  • +
+

Version 0.9.3 (2023-11-22)

+

What's New

+
    +
  • Add initial client with client_secret file. Thanks for @pidi3000
  • +
+

Version 0.9.2 (2023-09-26)

+

What's New

+
    +
  • Add new parameter for search method
  • +
  • Mark some parameter or method to be deprecated.
  • +
+

Version 0.9.1 (2023-07-19)

+

What's New

+ +

Version 0.9.0 (2022-12-26)

+

What's New

+
    +
  • Introduce new Client to operate YouTube DATA API. #120.
  • +
  • More example to show library usage.
  • +
+

Version 0.8.3 (2022-10-17)

+

What's New

+
    +
  • Add parts for video, thanks for @Omer
  • +
+

Version 0.8.2 (2022-03-16)

+

What's New

+
    +
  • Update OAuthorize functions.
  • +
  • Update for examples.
  • +
+

Version 0.8.1 (2021-05-14)

+

Deprecation

+

Detail at: https://developers.google.com/youtube/v3/revision_history#may-12,-2021

+
    +
  • Remove channel resource in brandingSettings for channel.
  • +
  • Remove localizations,targeting resource and some snippet resource for channelSection.
  • +
  • Remove tags in snippet for playlist.
  • +
+

Broken Change

+

Methods get_channel_sections_by_channel, get_channel_section_by_id has remove parameter hl.

+

Version 0.8.0

+

Broken Change

+

Modify the auth flow methods.

+

What's New

+
    +
  1. add python3.9 tests
  2. +
  3. New docs
  4. +
+

Version 0.7.0

+

What's New

+
    +
  1. Add api methods for members and membership levels
  2. +
  3. Add more examples for api
  4. +
  5. Add fields for playlist item api
  6. +
  7. fix some.
  8. +
+

Version 0.6.1

+

What's New

+

Remove deprecated api.

+

Version 0.6.0

+

What's New

+

Provide remain get apis. like activities, captions, channel_sections, i18n, video_abuse_report_reason, search resource and so on.

+

You can see the README_ to get more detail for those api.

+

Version 0.5.3

+

What's New

+

Provide the page token parameter to skip data have retrieved.

+

This for follow api methods

+
api.get_playlists()
+api.get_playlist_items()
+api.get_videos_by_chart()
+api.get_videos_by_myrating()
+api.get_comment_threads()
+api.get_comments()
+api.get_subscription_by_channel()
+api.get_subscription_by_me()
+
+

example

+
In[1]: r = api.get_subscription_by_channel(channel_id="UCAuUUnT6oDeKwE6v1NGQxug", limit=5, count=None, page_token="CAUQAA")
+In[2]:r.prevPageToken
+Out[2]: 'CAUQAQ'
+
+

Version 0.5.2

+

What's New

+

Now you can use authorized access token to get your subscriptions. +You can to the demo A demo for get my subscription to see simple usage. +Or you can see the subscriptions usage docs.

+
#43 add api for get my subscriptions
+
+#41 add api for channel subscriptions
+
+ +

Version 0.5.1

+

What's New

+

Now some apis can get all target items just by one method call.

+

For example, you can get playlist's all items by follow call

+
In [1]: r = api.get_playlist_items(playlist_id="PLWz5rJ2EKKc_xXXubDti2eRnIKU0p7wHd", parts=["id", "snippet"], count=None)
+In [2]: r.pageInfo
+Out[2]: PageInfo(totalResults=73, resultsPerPage=50)
+In [3]: len(r.items)
+Out[4]: 73
+
+

You can see the README to find which methods support this.

+

Version 0.5.0

+

Broken Change

+

Now introduce new model ApiResponse representing the response from youtube, so previous usage has been invalidated.

+

You need to read the docs README to get the simple new usage.

+

What's New

+

Split some method into multiple usage, for example get video has been split three methods:

+
    +
  • api.get_video_by_id()
  • +
  • api.get_videos_by_chart()
  • +
  • api.get_videos_by_myrating()
  • +
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 00000000..1cf13b9f Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.51d95adb.min.js b/assets/javascripts/bundle.51d95adb.min.js new file mode 100644 index 00000000..b20ec683 --- /dev/null +++ b/assets/javascripts/bundle.51d95adb.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Hi=Object.create;var xr=Object.defineProperty;var Pi=Object.getOwnPropertyDescriptor;var $i=Object.getOwnPropertyNames,kt=Object.getOwnPropertySymbols,Ii=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,an=Object.prototype.propertyIsEnumerable;var on=(e,t,r)=>t in e?xr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&on(e,r,t[r]);if(kt)for(var r of kt(t))an.call(t,r)&&on(e,r,t[r]);return e};var sn=(e,t)=>{var r={};for(var n in e)Er.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&kt)for(var n of kt(e))t.indexOf(n)<0&&an.call(e,n)&&(r[n]=e[n]);return r};var Ht=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Fi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $i(t))!Er.call(e,o)&&o!==r&&xr(e,o,{get:()=>t[o],enumerable:!(n=Pi(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Hi(Ii(e)):{},Fi(t||!e||!e.__esModule?xr(r,"default",{value:e,enumerable:!0}):r,e));var fn=Ht((wr,cn)=>{(function(e,t){typeof wr=="object"&&typeof cn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(wr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function s(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function f(T){var Ke=T.type,We=T.tagName;return!!(We==="INPUT"&&a[Ke]&&!T.readOnly||We==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function c(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(T){n=!1}function d(T){s(T.target)&&(n||f(T.target))&&c(T.target)}function h(T){s(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),B())}function B(){document.addEventListener("mousemove",z),document.addEventListener("mousedown",z),document.addEventListener("mouseup",z),document.addEventListener("pointermove",z),document.addEventListener("pointerdown",z),document.addEventListener("pointerup",z),document.addEventListener("touchmove",z),document.addEventListener("touchstart",z),document.addEventListener("touchend",z)}function re(){document.removeEventListener("mousemove",z),document.removeEventListener("mousedown",z),document.removeEventListener("mouseup",z),document.removeEventListener("pointermove",z),document.removeEventListener("pointerdown",z),document.removeEventListener("pointerup",z),document.removeEventListener("touchmove",z),document.removeEventListener("touchstart",z),document.removeEventListener("touchend",z)}function z(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,re())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),B(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var un=Ht(Sr=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},a=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(re,z){d.append(z,re)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(T){throw new Error("URL unable to set base "+c+" due to "+T)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,B=!0,re=this;["append","delete","set"].forEach(function(T){var Ke=h[T];h[T]=function(){Ke.apply(h,arguments),v&&(B=!1,re.search=h.toString(),B=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var z=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==z&&(z=this.search,B&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(f){Object.defineProperty(a,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){s(f)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Sr)});var Qr=Ht((Lt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Lt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Lt=="object"?Lt.ClipboardJS=r():t.ClipboardJS=r()})(Lt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ki}});var a=i(279),s=i.n(a),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var w=p()(O);return m("cut"),w},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",w=document.createElement("textarea");w.style.fontSize="12pt",w.style.border="0",w.style.padding="0",w.style.margin="0",w.style.position="absolute",w.style[O?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return w.style.top="".concat(k,"px"),w.setAttribute("readonly",""),w.value=j,w}var B=function(O,w){var k=v(O);w.container.appendChild(k);var F=p()(k);return m("copy"),k.remove(),F},re=function(O){var w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof O=="string"?k=B(O,w):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?k=B(O.value,w):(k=p()(O),m("copy")),k},z=re;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(w){return typeof w}:T=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},T(j)}var Ke=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},w=O.action,k=w===void 0?"copy":w,F=O.container,q=O.target,Le=O.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Le)return z(Le,{container:F});if(q)return k==="cut"?h(q):z(q,{container:F})},We=Ke;function Ie(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Ie=function(w){return typeof w}:Ie=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},Ie(j)}function Ti(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function nn(j,O){for(var w=0;w0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof F.action=="function"?F.action:this.defaultAction,this.target=typeof F.target=="function"?F.target:this.defaultTarget,this.text=typeof F.text=="function"?F.text:this.defaultText,this.container=Ie(F.container)==="object"?F.container:document.body}},{key:"listenClick",value:function(F){var q=this;this.listener=c()(F,"click",function(Le){return q.onClick(Le)})}},{key:"onClick",value:function(F){var q=F.delegateTarget||F.currentTarget,Le=this.action(q)||"copy",Rt=We({action:Le,container:this.container,target:this.target(q),text:this.text(q)});this.emit(Rt?"success":"error",{action:Le,text:Rt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(F){return yr("action",F)}},{key:"defaultTarget",value:function(F){var q=yr("target",F);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(F){return yr("text",F)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(F){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return z(F,q)}},{key:"cut",value:function(F){return h(F)}},{key:"isSupported",value:function(){var F=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof F=="string"?[F]:F,Le=!!document.queryCommandSupported;return q.forEach(function(Rt){Le=Le&&!!document.queryCommandSupported(Rt)}),Le}}]),w}(s()),ki=Ri},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function a(s,f){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(f))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return s(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=a(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return u(m,d,h);if(a.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return s(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),a=f.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var f=this;function c(){f.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=s.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var is=/["'&<>]/;Jo.exports=as;function as(e){var t=""+e,r=is.exec(t);if(!r)return t;var n,o="",i=0,a=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],a;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(s){a={error:s}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(a)throw a.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||s(m,d)})})}function s(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof Xe?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){s("next",m)}function u(m){s("throw",m)}function p(m,d){m(d),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof xe=="function"?xe(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(a){return new Promise(function(s,f){a=e[i](a),o(s,f,a.done,a.value)})}}function o(i,a,s,f){Promise.resolve(f).then(function(c){i({value:c,done:s})},a)}}function A(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var $t=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function De(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Fe=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=xe(a),f=s.next();!f.done;f=s.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var u=this.initialTeardown;if(A(u))try{u()}catch(v){i=v instanceof $t?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=xe(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{dn(h)}catch(v){i=i!=null?i:[],v instanceof $t?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new $t(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)dn(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&De(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&De(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Or=Fe.EMPTY;function It(e){return e instanceof Fe||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function dn(e){A(e)?e():e.unsubscribe()}var Ae={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,a=o.isStopped,s=o.observers;return i||a?Or:(this.currentObservers=null,s.push(r),new Fe(function(){n.currentObservers=null,De(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,a=n.isStopped;o?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new U;return r.source=this,r},t.create=function(r,n){return new wn(r,n)},t}(U);var wn=function(e){ne(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Or},t}(E);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ne(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,a=n._infiniteTimeWindow,s=n._timestampProvider,f=n._windowTime;o||(i.push(r),!a&&i.push(s.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,a=o._buffer,s=a.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var a=r.actions;n!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Ut);var On=function(e){ne(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Wt);var we=new On(Tn);var R=new U(function(e){return e.complete()});function Dt(e){return e&&A(e.schedule)}function kr(e){return e[e.length-1]}function Qe(e){return A(kr(e))?e.pop():void 0}function Se(e){return Dt(kr(e))?e.pop():void 0}function Vt(e,t){return typeof kr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function zt(e){return A(e==null?void 0:e.then)}function Nt(e){return A(e[ft])}function qt(e){return Symbol.asyncIterator&&A(e==null?void 0:e[Symbol.asyncIterator])}function Kt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function Ki(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Qt=Ki();function Yt(e){return A(e==null?void 0:e[Qt])}function Gt(e){return ln(this,arguments,function(){var r,n,o,i;return Pt(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,Xe(r.read())];case 3:return n=a.sent(),o=n.value,i=n.done,i?[4,Xe(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,Xe(o)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Bt(e){return A(e==null?void 0:e.getReader)}function $(e){if(e instanceof U)return e;if(e!=null){if(Nt(e))return Qi(e);if(pt(e))return Yi(e);if(zt(e))return Gi(e);if(qt(e))return _n(e);if(Yt(e))return Bi(e);if(Bt(e))return Ji(e)}throw Kt(e)}function Qi(e){return new U(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Yi(e){return new U(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?_(function(o,i){return e(o,i,n)}):me,Oe(1),r?He(t):zn(function(){return new Xt}))}}function Nn(){for(var e=[],t=0;t=2,!0))}function fe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,f=s===void 0?!0:s;return function(c){var u,p,m,d=0,h=!1,v=!1,B=function(){p==null||p.unsubscribe(),p=void 0},re=function(){B(),u=m=void 0,h=v=!1},z=function(){var T=u;re(),T==null||T.unsubscribe()};return g(function(T,Ke){d++,!v&&!h&&B();var We=m=m!=null?m:r();Ke.add(function(){d--,d===0&&!v&&!h&&(p=jr(z,f))}),We.subscribe(Ke),!u&&d>0&&(u=new et({next:function(Ie){return We.next(Ie)},error:function(Ie){v=!0,B(),p=jr(re,o,Ie),We.error(Ie)},complete:function(){h=!0,B(),p=jr(re,a),We.complete()}}),$(T).subscribe(u))})(c)}}function jr(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function V(e,t=document){let r=se(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function se(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),N(e===_e()),Y())}function Be(e){return{x:e.offsetLeft,y:e.offsetTop}}function Yn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,we),l(()=>Be(e)),N(Be(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,we),l(()=>rr(e)),N(rr(e)))}var Bn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!zr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),xa?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!zr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ya.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Jn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Zn=typeof WeakMap!="undefined"?new WeakMap:new Bn,eo=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=Ea.getInstance(),n=new Ra(t,r,this);Zn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){eo.prototype[e]=function(){var t;return(t=Zn.get(this))[e].apply(t,arguments)}});var ka=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:eo}(),to=ka;var ro=new E,Ha=I(()=>H(new to(e=>{for(let t of e)ro.next(t)}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function de(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){return Ha.pipe(S(t=>t.observe(e)),x(t=>ro.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(()=>de(e)))),N(de(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var no=new E,Pa=I(()=>H(new IntersectionObserver(e=>{for(let t of e)no.next(t)},{threshold:0}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function sr(e){return Pa.pipe(S(t=>t.observe(e)),x(t=>no.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function oo(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=de(e),o=bt(e);return r>=o.height-n.height-t}),Y())}var cr={drawer:V("[data-md-toggle=drawer]"),search:V("[data-md-toggle=search]")};function io(e){return cr[e].checked}function qe(e,t){cr[e].checked!==t&&cr[e].click()}function je(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),N(t.checked))}function $a(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ia(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(N(!1))}function ao(){let e=b(window,"keydown").pipe(_(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:io("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),_(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!$a(n,r)}return!0}),fe());return Ia().pipe(x(t=>t?R:e))}function Me(){return new URL(location.href)}function ot(e){location.href=e.href}function so(){return new E}function co(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)co(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)co(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function fo(){return location.hash.substring(1)}function uo(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Fa(){return b(window,"hashchange").pipe(l(fo),N(fo()),_(e=>e.length>0),J(1))}function po(){return Fa().pipe(l(e=>se(`[id="${e}"]`)),_(e=>typeof e!="undefined"))}function Nr(e){let t=matchMedia(e);return Zt(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function lo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(N(e.matches))}function qr(e,t){return e.pipe(x(r=>r?t():R))}function ur(e,t={credentials:"same-origin"}){return ve(fetch(`${e}`,t)).pipe(ce(()=>R),x(r=>r.status!==200?Tt(()=>new Error(r.statusText)):H(r)))}function Ue(e,t){return ur(e,t).pipe(x(r=>r.json()),J(1))}function mo(e,t){let r=new DOMParser;return ur(e,t).pipe(x(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function pr(e){let t=M("script",{src:e});return I(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(x(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),C(()=>document.head.removeChild(t)),Oe(1))))}function ho(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function bo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(ho),N(ho()))}function vo(){return{width:innerWidth,height:innerHeight}}function go(){return b(window,"resize",{passive:!0}).pipe(l(vo),N(vo()))}function yo(){return Q([bo(),go()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(X("size")),o=Q([n,r]).pipe(l(()=>Be(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:a,size:s},{x:f,y:c}])=>({offset:{x:a.x-f,y:a.y-c+i},size:s})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,f,c,u)=>{if(s===this.url.toString()){let p=new ErrorEvent("error",{message:a,filename:s,lineno:f,colno:c,error:u});this.dispatchEvent(p),this.onerror&&this.onerror(p)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Authorization

+ +

If you want to get some more data for your channel. You need provide the authorization first.

+

So, this doc show how to do authorize.

+

Prerequisite

+

At the beginning. You must know what is authorization.

+

You can see some information at the Official Documentation.

+

Then you need have an app with the Access scopes approval by YouTube.

+

If everything goes well. Now let do a simple authorize with Python-Youtube library.

+

Get authorization url

+

Suppose now we want to get user's permission to manage his youtube account.

+

For the Python-YouTube library, the default scopes are:

+
    +
  • https://www.googleapis.com/auth/youtube
  • +
  • https://www.googleapis.com/auth/userinfo.profile
  • +
+

You can get more scope information at Access scopes.

+

And We set the default redirect url is https://localhost/.

+

Now we can begin do the follows step.

+

Initialize the api instance with you app credentials

+
In [1]: from pyyoutube import Client
+
+In [2]: cli = Client(client_id="you client id", client_secret="you client secret")
+
+In [3]: cli.get_authorize_url()
+Out[3]:
+('https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=client_id&redirect_uri=https%3A%2F%2Flocalhost%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state=PyYouTube&access_type=offline&prompt=select_account',
+ 'PyYouTube')
+
+

Now you get the authorization url, you just need copy the link, and open browser to paste the link, click the enter bar.

+

Do authorization

+

If you enter the url. you will see this.

+

auth-1-chose-account

+

Now you need to chose or enter you google account with youtube.

+

If your app have not got the approval from youtube. You will get an warning from youtube. If you have been approved, you will +see the next image show directly.

+

auth-2-not-approval

+

For now, you need to click the button Advanced, then click the Go to Python-YouTube (unsafe).

+

auth-3-advanced

+

Now you can get a window to give permissions.

+

auth-4-allow-permission

+

click the blue button allow to give the permission.

+

Then you will get a Connection Error, don't worry. This just because we set the redirect link to localhost.

+

Retrieve access token

+

Now you need to copy the full url in the browser address bar. Then back to you console.

+
In [4]: token = cli.generate_access_token(authorization_response="the whole url")
+
+In [5]: token
+Out[5]: AccessToken(access_token='access token', expires_in=3600, token_type='Bearer')
+
+

now you have got your access token to visit your self data.

+

Get your data

+

For example, you can get your playlists.

+
In [6]: playlists = cli.playlists.list(mine=True)
+
+In [7]: playlists.items
+Out[7]:
+[Playlist(kind='youtube#playlist', id='PLBaidt0ilCManGDIKr8UVBFZwN_UvMKvS'),
+ Playlist(kind='youtube#playlist', id='PLBaidt0ilCMbUdj0EppB710c_X5OuCP2g')]
+
+
+

Tips

+

If you have some confuse. you need to read the Authorize Requests first.

+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/getting_started/index.html b/getting_started/index.html new file mode 100644 index 00000000..3a1487da --- /dev/null +++ b/getting_started/index.html @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Getting Started - Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Getting Started

+ +

This doc is a simple tutorial to show how to use this library to get data from YouTube DATA API.

+

You can get the whole description for YouTube API at YouTube API Reference.

+

Prerequisite

+

At the beginning. You need to create a Google Project by your google account.

+

Every new account has 12 project to cost.

+

Create your project

+

Click the Select a project-> NEW PROJECT to create a new project to use our library.

+

Fill the basic info to finish created.

+

gt-create-app-1

+

Enable YouTube DATA API service

+

Once the project created, the browser will redirect project home page.

+

Then click the ≡≡ symbol on the left top. Chose the APIs & Services tab.

+

You will see follow info.

+

gt-create-app-2

+

Click the + ENABLE APIS AND SERVICES symbol. And input YouTube DATA API to search.

+

gt-create-app-3

+

Then chose the YouTube DATA API item.

+

gt-create-app-4

+

Then click the ENABLE blue button. Now the service has been activated.

+

Create credentials

+

To use this API, you may need credentials. Click 'Create credentials' to get started.

+

gt-create-app-5

+

You need to fill in some information to create credentials.

+

Just chose YouTube DATA API v3, Other non-UI (e.g. cron job, daemon) and Public data.

+

Then click the blue button What credentials do I need? to create.

+

gt-create-app-6

+

Now you have generated one api key.

+

Use this key. You can retrieve public data for YouTube data by our library

+
from pyyoutube import Client
+
+cli = Client(api_key="your api key")
+
+

If you want to get some examples to see, check out the examples.

+

If you have an opens source application using python-youtube, send me a link, and I am very happy to add a link to it here.

+

But if you want to get user data by OAuth. You need create the credential for OAuth client ID.

+

And get more info at next page for Authorization.

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/images/auth-1-chose-account.png b/images/auth-1-chose-account.png new file mode 100644 index 00000000..4f60603c Binary files /dev/null and b/images/auth-1-chose-account.png differ diff --git a/images/auth-2-not-approval.png b/images/auth-2-not-approval.png new file mode 100644 index 00000000..94d762e8 Binary files /dev/null and b/images/auth-2-not-approval.png differ diff --git a/images/auth-3-advanced.png b/images/auth-3-advanced.png new file mode 100644 index 00000000..5794e54b Binary files /dev/null and b/images/auth-3-advanced.png differ diff --git a/images/auth-4-allow-permission.png b/images/auth-4-allow-permission.png new file mode 100644 index 00000000..dabed60c Binary files /dev/null and b/images/auth-4-allow-permission.png differ diff --git a/images/gt-create-app-1.png b/images/gt-create-app-1.png new file mode 100644 index 00000000..ddc28762 Binary files /dev/null and b/images/gt-create-app-1.png differ diff --git a/images/gt-create-app-2.png b/images/gt-create-app-2.png new file mode 100644 index 00000000..cdde7186 Binary files /dev/null and b/images/gt-create-app-2.png differ diff --git a/images/gt-create-app-3.png b/images/gt-create-app-3.png new file mode 100644 index 00000000..33242ab5 Binary files /dev/null and b/images/gt-create-app-3.png differ diff --git a/images/gt-create-app-4.png b/images/gt-create-app-4.png new file mode 100644 index 00000000..db754e57 Binary files /dev/null and b/images/gt-create-app-4.png differ diff --git a/images/gt-create-app-5.png b/images/gt-create-app-5.png new file mode 100644 index 00000000..682ed94d Binary files /dev/null and b/images/gt-create-app-5.png differ diff --git a/images/gt-create-app-6.png b/images/gt-create-app-6.png new file mode 100644 index 00000000..10eea7fa Binary files /dev/null and b/images/gt-create-app-6.png differ diff --git a/images/structure-uml.png b/images/structure-uml.png new file mode 100644 index 00000000..a48152c2 Binary files /dev/null and b/images/structure-uml.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..81488d55 --- /dev/null +++ b/index.html @@ -0,0 +1,660 @@ + + + + + + + + + + + + + + + + + + + + + + + + Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Welcome to Python-Youtube's documentation!

+

A Python wrapper around for YouTube Data API.

+

Author: IkarosKun merle.liukun@gmail.com

+

Introduction

+

With the YouTube Data API, you can add a variety of YouTube features to your application.

+

Use the API to upload videos, manage playlists and subscriptions, update channel settings, and more.

+

This library provides a Python interface for the YouTube DATA API.

+

Library could work on Python 3.6+.

+
+

Tips

+

This library only supports DATA API, It does not support Analytics and Reporting APIs and Live Streaming API.

+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/installation/index.html b/installation/index.html new file mode 100644 index 00000000..156540dc --- /dev/null +++ b/installation/index.html @@ -0,0 +1,697 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Installation - Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Installation

+ +

This library supports Python 3.6 and newer.

+

Dependencies

+

These following distributions will be installed automatically when installing Python-Youtube.

+
    +
  • requests: is an elegant and simple HTTP library for Python, built for human beings.
  • +
  • Requests-OAuthlib: uses the Python Requests and OAuthlib libraries to provide an easy-to-use Python interface for building OAuth1 and OAuth2 clients.
  • +
  • isodate: implements ISO 8601 date, time and duration parsing.
  • +
+

Installation

+

You can install this library from PyPI

+
$ pip install --upgrade python-youtube
+
+

Also, you can build this library from source code

+
$ git clone https://github.com/sns-sdks/python-youtube.git
+$ cd python-youtube
+$ make env
+$ make build
+
+

Testing

+

If you have been installing the requirements use make env. +You can use following command to test the code

+
$ make tests-html
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/introduce-new-structure/index.html b/introduce-new-structure/index.html new file mode 100644 index 00000000..44938535 --- /dev/null +++ b/introduce-new-structure/index.html @@ -0,0 +1,722 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Introduce Structure - Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Introduce Structure

+ +

This doc will show you the new api structure for this library.

+

Brief

+

To make the package easier to maintain and easy to use. We are shifted to using classes for different YouTube resources in an easier, higher-level programming experience.

+

structure-uml

+

In this structure, every resource will have self class. And to operate with YouTube API.

+

Simple usage

+

Initial Client

+
from pyyoutube import Client
+
+client = Client(api_key="your api key")
+
+

Get data.

+

for example to get channel data.

+
resp = client.channels.list(
+    parts=["id", "snippet"],
+    channel_id="UCa-vrCLQHviTOVnEKDOdetQ"    
+)
+# resp output
+# ChannelListResponse(kind='youtube#channelListResponse')
+# resp.items[0].id  output
+# UCa-vrCLQHviTOVnEKDOdetQ
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 00000000..e8c326a6 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to Python-Youtube's documentation!","text":"

A Python wrapper around for YouTube Data API.

Author: IkarosKun merle.liukun@gmail.com

"},{"location":"#introduction","title":"Introduction","text":"

With the YouTube Data API, you can add a variety of YouTube features to your application.

Use the API to upload videos, manage playlists and subscriptions, update channel settings, and more.

This library provides a Python interface for the YouTube DATA API.

Library could work on Python 3.6+.

Tips

This library only supports DATA API, It does not support Analytics and Reporting APIs and Live Streaming API.

"},{"location":"CHANGELOG/","title":"Changelog","text":"

All notable changes to this project will be documented in this file.

"},{"location":"CHANGELOG/#version-094-2024-02-18","title":"Version 0.9.4 (2024-02-18)","text":""},{"location":"CHANGELOG/#whats-new","title":"What's New","text":"
  • Add new parameter for_handle to get channel by handle.
  • fix some wrong error message.
"},{"location":"CHANGELOG/#version-093-2023-11-22","title":"Version 0.9.3 (2023-11-22)","text":""},{"location":"CHANGELOG/#whats-new_1","title":"What's New","text":"
  • Add initial client with client_secret file. Thanks for @pidi3000
"},{"location":"CHANGELOG/#version-092-2023-09-26","title":"Version 0.9.2 (2023-09-26)","text":""},{"location":"CHANGELOG/#whats-new_2","title":"What's New","text":"
  • Add new parameter for search method
  • Mark some parameter or method to be deprecated.
"},{"location":"CHANGELOG/#version-091-2023-07-19","title":"Version 0.9.1 (2023-07-19)","text":""},{"location":"CHANGELOG/#whats-new_3","title":"What's New","text":"
  • upgrade poetry. Thanks for @blaggacao
"},{"location":"CHANGELOG/#version-090-2022-12-26","title":"Version 0.9.0 (2022-12-26)","text":""},{"location":"CHANGELOG/#whats-new_4","title":"What's New","text":"
  • Introduce new Client to operate YouTube DATA API. #120.
  • More example to show library usage.
"},{"location":"CHANGELOG/#version-083-2022-10-17","title":"Version 0.8.3 (2022-10-17)","text":""},{"location":"CHANGELOG/#whats-new_5","title":"What's New","text":"
  • Add parts for video, thanks for @Omer
"},{"location":"CHANGELOG/#version-082-2022-03-16","title":"Version 0.8.2 (2022-03-16)","text":""},{"location":"CHANGELOG/#whats-new_6","title":"What's New","text":"
  • Update OAuthorize functions.
  • Update for examples.
"},{"location":"CHANGELOG/#version-081-2021-05-14","title":"Version 0.8.1 (2021-05-14)","text":""},{"location":"CHANGELOG/#deprecation","title":"Deprecation","text":"

Detail at: https://developers.google.com/youtube/v3/revision_history#may-12,-2021

  • Remove channel resource in brandingSettings for channel.
  • Remove localizations,targeting resource and some snippet resource for channelSection.
  • Remove tags in snippet for playlist.
"},{"location":"CHANGELOG/#broken-change","title":"Broken Change","text":"

Methods get_channel_sections_by_channel, get_channel_section_by_id has remove parameter hl.

"},{"location":"CHANGELOG/#version-080","title":"Version 0.8.0","text":""},{"location":"CHANGELOG/#broken-change_1","title":"Broken Change","text":"

Modify the auth flow methods.

"},{"location":"CHANGELOG/#whats-new_7","title":"What's New","text":"
  1. add python3.9 tests
  2. New docs
"},{"location":"CHANGELOG/#version-070","title":"Version 0.7.0","text":""},{"location":"CHANGELOG/#whats-new_8","title":"What's New","text":"
  1. Add api methods for members and membership levels
  2. Add more examples for api
  3. Add fields for playlist item api
  4. fix some.
"},{"location":"CHANGELOG/#version-061","title":"Version 0.6.1","text":""},{"location":"CHANGELOG/#whats-new_9","title":"What's New","text":"

Remove deprecated api.

"},{"location":"CHANGELOG/#version-060","title":"Version 0.6.0","text":""},{"location":"CHANGELOG/#whats-new_10","title":"What's New","text":"

Provide remain get apis. like activities, captions, channel_sections, i18n, video_abuse_report_reason, search resource and so on.

You can see the README_ to get more detail for those api.

"},{"location":"CHANGELOG/#version-053","title":"Version 0.5.3","text":""},{"location":"CHANGELOG/#whats-new_11","title":"What's New","text":"

Provide the page token parameter to skip data have retrieved.

This for follow api methods

api.get_playlists()\napi.get_playlist_items()\napi.get_videos_by_chart()\napi.get_videos_by_myrating()\napi.get_comment_threads()\napi.get_comments()\napi.get_subscription_by_channel()\napi.get_subscription_by_me()\n

example

In[1]: r = api.get_subscription_by_channel(channel_id=\"UCAuUUnT6oDeKwE6v1NGQxug\", limit=5, count=None, page_token=\"CAUQAA\")\nIn[2]:r.prevPageToken\nOut[2]: 'CAUQAQ'\n
"},{"location":"CHANGELOG/#version-052","title":"Version 0.5.2","text":""},{"location":"CHANGELOG/#whats-new_12","title":"What's New","text":"

Now you can use authorized access token to get your subscriptions. You can to the demo A demo for get my subscription to see simple usage. Or you can see the subscriptions usage docs.

#43 add api for get my subscriptions\n\n#41 add api for channel subscriptions\n
"},{"location":"CHANGELOG/#version-051","title":"Version 0.5.1","text":""},{"location":"CHANGELOG/#whats-new_13","title":"What's New","text":"

Now some apis can get all target items just by one method call.

For example, you can get playlist's all items by follow call

In [1]: r = api.get_playlist_items(playlist_id=\"PLWz5rJ2EKKc_xXXubDti2eRnIKU0p7wHd\", parts=[\"id\", \"snippet\"], count=None)\nIn [2]: r.pageInfo\nOut[2]: PageInfo(totalResults=73, resultsPerPage=50)\nIn [3]: len(r.items)\nOut[4]: 73\n

You can see the README to find which methods support this.

"},{"location":"CHANGELOG/#version-050","title":"Version 0.5.0","text":""},{"location":"CHANGELOG/#broken-change_2","title":"Broken Change","text":"

Now introduce new model ApiResponse representing the response from youtube, so previous usage has been invalidated.

You need to read the docs README to get the simple new usage.

"},{"location":"CHANGELOG/#whats-new_14","title":"What's New","text":"

Split some method into multiple usage, for example get video has been split three methods:

  • api.get_video_by_id()
  • api.get_videos_by_chart()
  • api.get_videos_by_myrating()
"},{"location":"authorization/","title":"Authorization","text":"

If you want to get some more data for your channel. You need provide the authorization first.

So, this doc show how to do authorize.

"},{"location":"authorization/#prerequisite","title":"Prerequisite","text":"

At the beginning. You must know what is authorization.

You can see some information at the Official Documentation.

Then you need have an app with the Access scopes approval by YouTube.

If everything goes well. Now let do a simple authorize with Python-Youtube library.

"},{"location":"authorization/#get-authorization-url","title":"Get authorization url","text":"

Suppose now we want to get user's permission to manage his youtube account.

For the Python-YouTube library, the default scopes are:

  • https://www.googleapis.com/auth/youtube
  • https://www.googleapis.com/auth/userinfo.profile

You can get more scope information at Access scopes.

And We set the default redirect url is https://localhost/.

Now we can begin do the follows step.

Initialize the api instance with you app credentials

In [1]: from pyyoutube import Client\n\nIn [2]: cli = Client(client_id=\"you client id\", client_secret=\"you client secret\")\n\nIn [3]: cli.get_authorize_url()\nOut[3]:\n('https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=client_id&redirect_uri=https%3A%2F%2Flocalhost%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state=PyYouTube&access_type=offline&prompt=select_account',\n 'PyYouTube')\n

Now you get the authorization url, you just need copy the link, and open browser to paste the link, click the enter bar.

"},{"location":"authorization/#do-authorization","title":"Do authorization","text":"

If you enter the url. you will see this.

Now you need to chose or enter you google account with youtube.

If your app have not got the approval from youtube. You will get an warning from youtube. If you have been approved, you will see the next image show directly.

For now, you need to click the button Advanced, then click the Go to Python-YouTube (unsafe).

Now you can get a window to give permissions.

click the blue button allow to give the permission.

Then you will get a Connection Error, don't worry. This just because we set the redirect link to localhost.

"},{"location":"authorization/#retrieve-access-token","title":"Retrieve access token","text":"

Now you need to copy the full url in the browser address bar. Then back to you console.

In [4]: token = cli.generate_access_token(authorization_response=\"the whole url\")\n\nIn [5]: token\nOut[5]: AccessToken(access_token='access token', expires_in=3600, token_type='Bearer')\n

now you have got your access token to visit your self data.

"},{"location":"authorization/#get-your-data","title":"Get your data","text":"

For example, you can get your playlists.

In [6]: playlists = cli.playlists.list(mine=True)\n\nIn [7]: playlists.items\nOut[7]:\n[Playlist(kind='youtube#playlist', id='PLBaidt0ilCManGDIKr8UVBFZwN_UvMKvS'),\n Playlist(kind='youtube#playlist', id='PLBaidt0ilCMbUdj0EppB710c_X5OuCP2g')]\n

Tips

If you have some confuse. you need to read the Authorize Requests first.

"},{"location":"getting_started/","title":"Getting Started","text":"

This doc is a simple tutorial to show how to use this library to get data from YouTube DATA API.

You can get the whole description for YouTube API at YouTube API Reference.

"},{"location":"getting_started/#prerequisite","title":"Prerequisite","text":"

At the beginning. You need to create a Google Project by your google account.

Every new account has 12 project to cost.

"},{"location":"getting_started/#create-your-project","title":"Create your project","text":"

Click the Select a project-> NEW PROJECT to create a new project to use our library.

Fill the basic info to finish created.

"},{"location":"getting_started/#enable-youtube-data-api-service","title":"Enable YouTube DATA API service","text":"

Once the project created, the browser will redirect project home page.

Then click the \u2261\u2261 symbol on the left top. Chose the APIs & Services tab.

You will see follow info.

Click the + ENABLE APIS AND SERVICES symbol. And input YouTube DATA API to search.

Then chose the YouTube DATA API item.

Then click the ENABLE blue button. Now the service has been activated.

"},{"location":"getting_started/#create-credentials","title":"Create credentials","text":"

To use this API, you may need credentials. Click 'Create credentials' to get started.

You need to fill in some information to create credentials.

Just chose YouTube DATA API v3, Other non-UI (e.g. cron job, daemon) and Public data.

Then click the blue button What credentials do I need? to create.

Now you have generated one api key.

Use this key. You can retrieve public data for YouTube data by our library

from pyyoutube import Client\n\ncli = Client(api_key=\"your api key\")\n

If you want to get some examples to see, check out the examples.

If you have an opens source application using python-youtube, send me a link, and I am very happy to add a link to it here.

But if you want to get user data by OAuth. You need create the credential for OAuth client ID.

And get more info at next page for Authorization.

"},{"location":"installation/","title":"Installation","text":"

This library supports Python 3.6 and newer.

"},{"location":"installation/#dependencies","title":"Dependencies","text":"

These following distributions will be installed automatically when installing Python-Youtube.

  • requests: is an elegant and simple HTTP library for Python, built for human beings.
  • Requests-OAuthlib: uses the Python Requests and OAuthlib libraries to provide an easy-to-use Python interface for building OAuth1 and OAuth2 clients.
  • isodate: implements ISO 8601 date, time and duration parsing.
"},{"location":"installation/#installation","title":"Installation","text":"

You can install this library from PyPI

$ pip install --upgrade python-youtube\n

Also, you can build this library from source code

$ git clone https://github.com/sns-sdks/python-youtube.git\n$ cd python-youtube\n$ make env\n$ make build\n
"},{"location":"installation/#testing","title":"Testing","text":"

If you have been installing the requirements use make env. You can use following command to test the code

$ make tests-html\n
"},{"location":"introduce-new-structure/","title":"Introduce Structure","text":"

This doc will show you the new api structure for this library.

"},{"location":"introduce-new-structure/#brief","title":"Brief","text":"

To make the package easier to maintain and easy to use. We are shifted to using classes for different YouTube resources in an easier, higher-level programming experience.

In this structure, every resource will have self class. And to operate with YouTube API.

"},{"location":"introduce-new-structure/#simple-usage","title":"Simple usage","text":""},{"location":"introduce-new-structure/#initial-client","title":"Initial Client","text":"
from pyyoutube import Client\n\nclient = Client(api_key=\"your api key\")\n
"},{"location":"introduce-new-structure/#get-data","title":"Get data.","text":"

for example to get channel data.

resp = client.channels.list(\n    parts=[\"id\", \"snippet\"],\n    channel_id=\"UCa-vrCLQHviTOVnEKDOdetQ\"    \n)\n# resp output\n# ChannelListResponse(kind='youtube#channelListResponse')\n# resp.items[0].id  output\n# UCa-vrCLQHviTOVnEKDOdetQ\n
"},{"location":"usage/work-with-api/","title":"Work with Api","text":"

Tips

This is previous version to operate YouTube DATA API.

We recommend using the latest version of methods to operate YouTube DATA API.

The API is exposed via the pyyoutube.Api class.

"},{"location":"usage/work-with-api/#instantiate","title":"INSTANTIATE","text":"

There provide two method to create instance the pyyoutube.Api.

You can just initialize with an api key.

>>> from pyyoutube import Api\n\n>>> api = Api(api_key=\"your api key\")\n

If you want to get some authorization data. you need to initialize with access token.

>>> from pyyoutube import Api\n\n>>> api = Api(access_token='your api key')\n

You can read the docs to see how to get an access token.

Or you can ask for user to do oauth flow:

>>> from pyyoutube import Api\n\n>>> api = Api(client_id=\"client key\", client_secret=\"client secret\")\n# Get authorization url\n>>> api.get_authorization_url()\n# ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=id&redirect_uri=https%3A%2F%2Flocalhost%2F&scope=scope&state=PyYouTube&access_type=offline&prompt=select_account', 'PyYouTube')\n# user to do\n# copy the response url\n>>> api.generate_access_token(authorization_response=\"link for response\")\n# AccessToken(access_token='token', expires_in=3599, token_type='Bearer')\n
"},{"location":"usage/work-with-api/#usage","title":"Usage","text":"

Now you can use the instance to get data from YouTube.

"},{"location":"usage/work-with-api/#channel-data","title":"CHANNEL DATA","text":"

The library provides several ways to get channel's data.

If a channel is not found, the property items will return with blank list.

You can use channel id:

>>> channel_by_id = api.get_channel_info(channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw\")\n>>> channel_by_id.items\n[Channel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw')]\n>>> channel_by_id.items[0].to_dict()\n{'kind': 'youtube#channel',\n 'etag': '\"j6xRRd8dTPVVptg711_CSPADRfg/AW8QEqbNRoIJv9KuzCIg0CG6aJA\"',\n 'id': 'UC_x5XG1OV2P6uZZ5FSM9Ttw',\n 'snippet': {'title': 'Google Developers',\n  'description': 'The Google Developers channel features talks from events, educational series, best practices, tips, and the latest updates across our products and platforms.',\n  'customUrl': 'googlecode',\n  'publishedAt': '2007-08-23T00:34:43.000Z',\n  'thumbnails': {'default': {'url': 'https://yt3.ggpht.com/a/AGF-l78iFtAxyRZcUBzG91kbKMES19z-zGW5KT20_g=s88-c-k-c0xffffffff-no-rj-mo',\n    'width': 88,\n    'height': 88},\n   'medium': {'url': 'https://yt3.ggpht.com/a/AGF-l78iFtAxyRZcUBzG91kbKMES19z-zGW5KT20_g=s240-c-k-c0xffffffff-no-rj-mo',\n    'width': 240,\n    'height': 240},\n   'high': {'url': 'https://yt3.ggpht.com/a/AGF-l78iFtAxyRZcUBzG91kbKMES19z-zGW5KT20_g=s800-c-k-c0xffffffff-no-rj-mo',\n    'width': 800,\n    'height': 800},\n   'standard': None,\n   'maxres': None},\n  'defaultLanguage': None,\n  'localized': {'title': 'Google Developers',\n   'description': 'The Google Developers channel features talks from events, educational series, best practices, tips, and the latest updates across our products and platforms.'},\n  'country': 'US'},\n  ...\n  }\n

You can pass a channel id with comma-separated id string or a list, tuple or set of ids to get multiple channels. Many methods also provide this functionality.

with ids:

>>> channel_by_ids = api.get_channel_info(channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw,UCa-vrCLQHviTOVnEKDOdetQ\")\n>>> channel_by_ids.items\n[Channel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw'),\n Channel(kind='youtube#channel', id='UCa-vrCLQHviTOVnEKDOdetQ')]\n

You can also use channel name:

>>> channel_by_username = api.get_channel_info(for_username=\"GoogleDevelopers\")\n>>> channel_by_username.items[0]\nChannel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw')\n

If you have authorized, you can get your channels:

>>> channel_by_mine = api_with_authorization.get_channel_info(mine=True)\n>>> channel_by_mine.items[0]\nChannel(kind='youtube#channel', id='UCa-vrCLQHviTOVnEKDOdetQ')\n

Tips

To get your channel, you must do authorization first, otherwise you will get an error.

"},{"location":"usage/work-with-api/#playlist","title":"PLAYLIST","text":"

There are methods to get playlists by playlist id, channel id or get your own playlists.

Get playlists by id:

>>> playlists_by_id = api.get_playlist_by_id(playlist_id=\"PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw\")\n>>> playlists_by_id.items\n[Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw')]\n

Get playlists by channel (If you want to get all playlists for the target channel's , just provide the parameter count=None):

>>> playlists_by_channel = api.get_playlists(channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw\")\n>>> playlists_by_channel.items\n[Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw'),\n Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIJO83u2UmyC8ud41AvUnhgj'),\n Playlist(kind='youtube#playlist', id='PLOU2XLYxmsILfV1LiUhDjbh1jkFjQWrYB'),\n Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIKNr3Wfhm8o0TSojW7hEPPY'),\n Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIJ8ItHmK4bRlY4GCzMgXLAJ')]\n

Get your playlists(this requires authorization):

>>> playlists_by_mine = api.get_playlists(mine=True)\n
"},{"location":"usage/work-with-api/#playlist-item","title":"PLAYLIST ITEM","text":"

Similarly, you can get playlist items by playlist item id or playlist id.

Get playlist items by id:

>>> playlist_item_by_id = api.get_playlist_item_by_id(playlist_item_id=\"UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA\"\n...     \"1c28wZkF3d2ZUdy41NkI0NEY2RDEwNTU3Q0M2\")\n\n>>> playlist_item_by_id.items\n[PlaylistItem(kind='youtube#playlistItem', id='UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA1c28wZkF3d2ZUdy41NkI0NEY2RDEwNTU3Q0M2')]\n

Get playlist items by playlist id (If you want to get target playlist all items, just provide the parameter count=None):

>>> playlist_item_by_playlist = api.get_playlist_items(playlist_id=\"PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw\", count=2)\n\n>>> playlist_item_by_playlist.items\n[PlaylistItem(kind='youtube#playlistItem', id='UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA1c28wZkF3d2ZUdy41NkI0NEY2RDEwNTU3Q0M2'),\n PlaylistItem(kind='youtube#playlistItem', id='UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA1c28wZkF3d2ZUdy4yODlGNEE0NkRGMEEzMEQy')]\n>>> playlist_item_by_id.items[0].snippet.resourceId\nResourceId(kind='youtube#video', videoId='CvTApw9X8aA')\n
"},{"location":"usage/work-with-api/#video","title":"VIDEO","text":"

You can get a video's information by several methods.

Get videos by video id(s):

>>> video_by_id = api.get_video_by_id(video_id=\"CvTApw9X8aA\")\n\n>>> video_by_id\nVideoListResponse(kind='youtube#videoListResponse')\n\n>>> video_by_id.items\n[Video(kind='youtube#video', id='CvTApw9X8aA')]\n

Get videos by chart (If you want to get all videos, just provide the parameter count=None):

>>> video_by_chart = api.get_videos_by_chart(chart=\"mostPopular\", region_code=\"US\", count=2)\n\n>>> video_by_chart.items\n[Video(kind='youtube#video', id='RwnN2FVaHmw'),\n Video(kind='youtube#video', id='hDeuSfo_Ys0')]\n

Get videos by your rating (this requires authorization, also if you want to get all videos, just provide the parameter count=None):

>>> videos_by_rating = api.get_videos_by_myrating(rating=\"like\", count=2)\n
"},{"location":"usage/work-with-api/#comment-thread","title":"COMMENT THREAD","text":"

You can get comment thread information by id or some filter.

Get comment thread by id(s):

>>> ct_by_id = api.get_comment_thread_by_id(comment_thread_id='Ugz097FRhsQy5CVhAjp4AaABAg,UgzhytyP79_Pwa\n... Dd4UB4AaABAg')\n\n>>> ct_by_id.items\n[CommentThread(kind='youtube#commentThread', id='Ugz097FRhsQy5CVhAjp4AaABAg'),\n CommentThread(kind='youtube#commentThread', id='UgzhytyP79_PwaDd4UB4AaABAg')]\n

Get all comment threads related to a channel (including comment threads for the channel's video, also if you want to get all comment threads, just provide the parameter count=None):

>>> ct_by_all = api.get_comment_threads(all_to_channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw\", count=2)\n\n>>> ct_by_all.items\n[CommentThread(kind='youtube#commentThread', id='UgwlB_Cza9WtzUWahYN4AaABAg'),\n CommentThread(kind='youtube#commentThread', id='UgyvoQJ2LsxCBwGEpMB4AaABAg')]\n

Get comment threads only for the channel (If you want to get all comment threads, just provide the parameter count=None):

>>> ct_by_channel = api.get_comment_threads(channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw\", count=2)\n\n>>> ct_by_channel.items\n[CommentThread(kind='youtube#commentThread', id='UgyUBI0HsgL9emxcZpR4AaABAg'),\n CommentThread(kind='youtube#commentThread', id='Ugzi3lkqDPfIOirGFLh4AaABAg')]\n

Get comment threads only for the video (If you want to get all comment threads, just provide the parameter count=None):

>>> ct_by_video = api.get_comment_threads(video_id=\"D-lhorsDlUQ\", count=2)\n\n>>> ct_by_video.items\n[CommentThread(kind='youtube#commentThread', id='UgydxWWoeA7F1OdqypJ4AaABAg'),\n CommentThread(kind='youtube#commentThread', id='UgxKREWxIgDrw8w2e_Z4AaABAg')]\n
"},{"location":"usage/work-with-api/#comment","title":"COMMENT","text":"

You can get comment information by id or use the top-level comment id to get replies.

Tips

The reply has the same structure as a comment.

Get comments by id(s):

>>> comment_by_id = api.get_comment_by_id(comment_id='UgxKREWxIgDrw8w2e_Z4AaABAg,UgyrVQaFfEdvaSzstj14AaABAg')\n\n>>> comment_by_id.items\n[Comment(kind='youtube#comment', id='UgxKREWxIgDrw8w2e_Z4AaABAg', snippet=CommentSnippet(authorDisplayName='Hieu Nguyen', likeCount=0)),\n Comment(kind='youtube#comment', id='UgyrVQaFfEdvaSzstj14AaABAg', snippet=CommentSnippet(authorDisplayName='Mani Kanta', likeCount=0))]\n

Get replies by comment id (If you want to get all comments, just provide the parameter count=None):

>>> comment_by_parent = api.get_comments(parent_id=\"UgwYjZXfNCUTKPq9CZp4AaABAg\")\n>>> comment_by_parent.items\n[Comment(kind='youtube#comment', id='UgwYjZXfNCUTKPq9CZp4AaABAg.8yxhlQJogG18yz_cXK9Kcj', snippet=CommentSnippet(authorDisplayName='Marlon L\u00f3pez', likeCount=0))]\n
"},{"location":"usage/work-with-api/#video-category","title":"VIDEO CATEGORY","text":"

You can get video category with id or region.

Get video categories with id(s):

>>> video_category_by_id = api.get_video_categories(category_id=\"17,18\")\n\n>>> video_category_by_id.items\n[VideoCategory(kind='youtube#videoCategory', id='17'),\n VideoCategory(kind='youtube#videoCategory', id='18')]\n

Get video categories with region code:

>>> video_categories_by_region = api.get_video_categories(region_code=\"US\")\n\n>>> video_categories_by_region.items\n[VideoCategory(kind='youtube#videoCategory', id='1'),\n VideoCategory(kind='youtube#videoCategory', id='2'),\n VideoCategory(kind='youtube#videoCategory', id='10'),\n VideoCategory(kind='youtube#videoCategory', id='15'),\n ...]\n
"},{"location":"usage/work-with-api/#subscriptions","title":"SUBSCRIPTIONS","text":"

You can get subscription information by id, by point channel, or your own.

Tips

If you want to get the subscriptions not set to public, you need do authorization first and get the access token. You can see the demo A demo for get my subscription.

To get subscription info by id(s), this needs your token to have the permission for the subscriptions belonging to a channel or user:

>>> r = api.get_subscription_by_id(\n...         subscription_id=[\n...             \"zqShTXi-2-Tx7TtwQqhCBwViE_j9IEgnmRmPnqJljxo\",\n...             \"zqShTXi-2-Rya5uUxEp3ZsPI3fZrFQnSXNQCwvHBGGo\"])\n>>> r\nSubscriptionListResponse(kind='youtube#subscriptionListResponse')\n>>> r.items\n[Subscription(kind='youtube#subscription', id='zqShTXi-2-Tx7TtwQqhCBwViE_j9IEgnmRmPnqJljxo', snippet=SubscriptionSnippet(title='PyCon 2015', description='')),\n Subscription(kind='youtube#subscription', id='zqShTXi-2-Rya5uUxEp3ZsPI3fZrFQnSXNQCwvHBGGo', snippet=SubscriptionSnippet(title='ikaros-life', description='This is a test channel.'))]\n

Get your own subscriptions, this need you do authorization first or give the authorized access token:

>>> r = api.get_subscription_by_me(\n...         mine=True,\n...         parts=[\"id\", \"snippet\"],\n...         count=2\n... )\n>>> r\nSubscriptionListResponse(kind='youtube#subscriptionListResponse')\n>>> r.items\n[Subscription(kind='youtube#subscription', id='zqShTXi-2-Tx7TtwQqhCBwtJ-Aho6DZeutqZiP4Q79Q', snippet=SubscriptionSnippet(title='Next Day Video', description='')),\n Subscription(kind='youtube#subscription', id='zqShTXi-2-Tx7TtwQqhCBwViE_j9IEgnmRmPnqJljxo', snippet=SubscriptionSnippet(title='PyCon 2015', description=''))]\n

Get public channel's subscriptions:

>>> r = api.get_subscription_by_channel(\n...      channel_id=\"UCAuUUnT6oDeKwE6v1NGQxug\",\n...      parts=\"id,snippet\",\n...      count=2\n... )\n>>> r\nSubscriptionListResponse(kind='youtube#subscriptionListResponse')\n>>> r.items\n[Subscription(kind='youtube#subscription', id='FMP3Mleijt-52zZDGkHtR5KhwkvCcdQKWWWIA1j5eGc', snippet=SubscriptionSnippet(title='TEDx Talks', description=\"TEDx is an international community that organizes TED-style events anywhere and everywhere -- celebrating locally-driven ideas and elevating them to a global stage. TEDx events are produced independently of TED conferences, each event curates speakers on their own, but based on TED's format and rules.\\n\\nFor more information on using TED for commercial purposes (e.g. employee learning, in a film, or in an online course), please submit a media request using the link below.\")),\n Subscription(kind='youtube#subscription', id='FMP3Mleijt_ZKvy5M-HhRlsqI4wXY7VmP5g8lvmRhVU', snippet=SubscriptionSnippet(title='TED Residency', description='The TED Residency program is an incubator for breakthrough ideas. It is free and open to all via a semi-annual competitive application. Those chosen as TED Residents spend four months at TED headquarters in New York City, working on their idea. Selection criteria include the strength of their idea, their character, and their ability to bring a fresh perspective and positive contribution to the diverse TED community.'))]\n
"},{"location":"usage/work-with-api/#activities","title":"ACTIVITIES","text":"

You can get activities by channel id. You can also get your own activities after you have completed authorization.

Get public channel activities:

>>> r = api.get_activities_by_channel(channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw\", count=2)\n>>> r\nActivityListResponse(kind='youtube#activityListResponse')\n>>> r.items\n[Activity(kind='youtube#activity', id='MTUxNTc3NzM2MDAyODIxOTQxNDM0NjAwMA==', snippet=ActivitySnippet(title='2019 Year in Review - The Developer Show', description='Here to bring you the latest developer news from across Google this year is Developer Advocate Timothy Jordan. In this last week of the year, we\u2019re taking a look back at some of the coolest and biggest announcements we covered in 2019! \\n\\nFollow Google Developers on Instagram \u2192 https://goo.gle/googledevs\\n\\nWatch more #DevShow \u2192 https://goo.gle/GDevShow\\nSubscribe to Google Developers \u2192 https://goo.gle/developers')),\n Activity(kind='youtube#activity', id='MTUxNTc3MTI4NzIzODIxOTQxNDM0NzI4MA==', snippet=ActivitySnippet(title='GDE Promo - Lara Martin', description='Meet Lara Martin, a Flutter/Dart Google Developers Expert and get inspired by her journey. Watch now for a preview of her story! #GDESpotlights #IncludedWithGoogle\\n\\nLearn about the GDE program \u2192 https://goo.gle/2qWOvAy\\n\\nGoogle Developers Experts \u2192 https://goo.gle/GDE\\nSubscribe to Google Developers \u2192 https://goo.gle/developers'))]\n

Get your activities:

>>> r = api_with_token.get_activities_by_me()\n>>> r.items\n[Activity(kind='youtube#activity', id='MTUxNTc0OTk2MjI3NDE0MjYwMDY1NjAwODA=', snippet=ActivitySnippet(title='\u534e\u5c71\u65e5\u51fa', description='\u51b7\u51b7\u7684\u5c71\u5934')),\n Activity(kind='youtube#activity', id='MTUxNTc0OTk1OTAyNDE0MjYwMDY1NTc2NDg=', snippet=ActivitySnippet(title='\u6d77\u4e0a\u65e5\u51fa', description='\u7f8e\u7f8e\u7f8e'))]\n

Get your video captions:

>>> r = api.get_captions_by_video(video_id=\"oHR3wURdJ94\", parts=[\"id\", \"snippet\"])\n>>> r\nCaptionListResponse(kind='youtube#captionListResponse')\n>>> r.items\n[Caption(kind='youtube#caption', id='SwPOvp0r7kd9ttt_XhcHdZthMwXG7Z0I', snippet=CaptionSnippet(videoId='oHR3wURdJ94', lastUpdated='2020-01-14T09:40:49.981Z')),\n Caption(kind='youtube#caption', id='fPMuDm722CIRcUAT3NTPQHQZJZJxt39kU7JvrHk8Kzs=', snippet=CaptionSnippet(videoId='oHR3wURdJ94', lastUpdated='2020-01-14T09:39:46.991Z'))]\n

If you already have caption id(s), you can get video caption by id(s):

>>> r = api.get_captions_by_video(video_id=\"oHR3wURdJ94\", parts=[\"id\", \"snippet\"], caption_id=\"SwPOvp0r7kd9ttt_XhcHdZthMwXG7Z0I\")\n>>> r\nCaptionListResponse(kind='youtube#captionListResponse')\n>>> r.items\n[Caption(kind='youtube#caption', id='SwPOvp0r7kd9ttt_XhcHdZthMwXG7Z0I', snippet=CaptionSnippet(videoId='oHR3wURdJ94', lastUpdated='2020-01-14T09:40:49.981Z'))]\n
"},{"location":"usage/work-with-api/#channel-sections","title":"CHANNEL SECTIONS","text":"

You can get channel sections by self id or belonged channel id or your own channel.

Get channel sections by channel id:

>>> r = api.get_channel_sections_by_channel(channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw\")\n>>>> r\nChannelSectionResponse(kind='youtube#channelSectionListResponse')\n>>> r.items\n[ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.e-Fk7vMPqLE'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.B8DTd9ZXJqM'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.MfvRjkWLxgk'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.fEjJOXRoWwg'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.PvTmxDBxtLs'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.pmcIOsL7s98'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.c3r3vYf9uD0'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.ZJpkBl-mXfM'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.9_wU0qhEPR8'),\n ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.npYvuMz0_es')]\n

Get authorized user's channel sections:

>>> r = api.get_channel_sections_by_channel(mine=True)\n>>> r.items\n[ChannelSection(kind='youtube#channelSection', id='UCa-vrCLQHviTOVnEKDOdetQ.jNQXAC9IVRw'),\n ChannelSection(kind='youtube#channelSection', id='UCa-vrCLQHviTOVnEKDOdetQ.LeAltgu_pbM'),\n ChannelSection(kind='youtube#channelSection', id='UCa-vrCLQHviTOVnEKDOdetQ.nGzAI5pLbMY')]\n

Get channel section detail info by id:

>>> r = api.get_channel_section_by_id(section_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw.e-Fk7vMPqLE\")\n>>> r\nChannelSectionResponse(kind='youtube#channelSectionListResponse')\n>>> r1.items\n[ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.e-Fk7vMPqLE')]\n
"},{"location":"usage/work-with-api/#i18n-resource","title":"I18N RESOURCE","text":"

You can get a list of content regions that the YouTube website supports:

>>> r = api.get_i18n_regions(parts=[\"snippet\"])\n>>> r.items\n[I18nRegion(kind='youtube#i18nRegion', id='DZ', snippet=I18nRegionSnippet(gl='DZ', name='Algeria')),\n I18nRegion(kind='youtube#i18nRegion', id='AR', snippet=I18nRegionSnippet(gl='AR', name='Argentina')),\n I18nRegion(kind='youtube#i18nRegion', id='AU', snippet=I18nRegionSnippet(gl='AU', name='Australia'))\n ...]\n

You can get a list of application languages that the YouTube website supports:

>>> r = api.get_i18n_languages(parts=[\"snippet\"])\n>>> r.items\n[I18nLanguage(kind='youtube#i18nLanguage', id='af', snippet=I18nLanguageSnippet(hl='af', name='Afrikaans')),\n I18nLanguage(kind='youtube#i18nLanguage', id='az', snippet=I18nLanguageSnippet(hl='az', name='Azerbaijani')),\n I18nLanguage(kind='youtube#i18nLanguage', id='id', snippet=I18nLanguageSnippet(hl='id', name='Indonesian')),\n ...]\n
"},{"location":"usage/work-with-api/#member","title":"MEMBER","text":"

The API request must be authorized by the channel owner.

You can retrieve a list of members (formerly known as \"sponsors\") for a channel:

>>> r = api_with_token.get_members(parts=[\"snippet\"])\n>>> r.items\n[MemberListResponse(kind='youtube#memberListResponse'),\n MemberListResponse(kind='youtube#memberListResponse')]\n
"},{"location":"usage/work-with-api/#membership-level","title":"MEMBERSHIP LEVEL","text":"

The API request must be authorized by the channel owner.

You can retrieve a list membership levels for a channel:

>>> r = api_with_token.get_membership_levels(parts=[\"snippet\"])\n>>> r.items\n[MembershipsLevelListResponse(kind='youtube#membershipsLevelListResponse'),\n MembershipsLevelListResponse(kind='youtube#membershipsLevelListResponse')]\n
"},{"location":"usage/work-with-api/#video-abuse-report-reason","title":"VIDEO ABUSE REPORT REASON","text":"

You can retrieve a list of reasons that can be used to report abusive videos:

>>> r = api_with_token.get_video_abuse_report_reason(parts=[\"snippet\"])\n>>> r.items\n[VideoAbuseReportReason(kind='youtube#videoAbuseReportReason'),\n VideoAbuseReportReason(kind='youtube#videoAbuseReportReason')]\n
"},{"location":"usage/work-with-api/#search","title":"SEARCH","text":"

You can use those methods to search the video,playlist,channel data. For more info, you can see the Search Request Docs.

You can search different type of resource with keywords:

>>> r = api.search_by_keywords(q=\"surfing\", search_type=[\"channel\",\"video\", \"playlist\"], count=5, limit=5)\n>>> r.items\n[SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult')]\n

You can search your app send videos:

>>> r = api_with_token.search_by_developer(q=\"news\", count=1)\n>>> r.items\n[SearchResult(kind='youtube#searchResult')]\n

You can search your videos:

>>> r = api_with_token.search_by_mine(q=\"news\", count=1)\n>>> r.items\n[SearchResult(kind='youtube#searchResult')]\n

Or you can build your request using the search method:

>>> r = api.search(\n...     location=\"21.5922529, -158.1147114\",\n...     location_radius=\"10mi\",\n...     q=\"surfing\",\n...     parts=[\"snippet\"],\n...     count=5,\n...     published_after=\"2020-02-01T00:00:00Z\",\n...     published_before=\"2020-03-01T00:00:00Z\",\n...     safe_search=\"moderate\",\n...     search_type=\"video\")\n>>> r.items\n[SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult')]\n\n>>> r = api.search(\n...     event_type=\"live\",\n...     q=\"news\",\n...     count=3,\n...     parts=[\"snippet\"],\n...     search_type=\"video\",\n...     topic_id=\"/m/09s1f\",\n...     order=\"viewCount\")\n>>> r.items\n[SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult'),\n SearchResult(kind='youtube#searchResult')]\n
"},{"location":"usage/work-with-client/","title":"Work with Client","text":"

We have refactored the project code to support more methods and improve code usability.

And new structure like follows.

In this structure, we identify each entity as a class of resources and perform operations on the resources.

"},{"location":"usage/work-with-client/#instantiate","title":"INSTANTIATE","text":"

Client is exposed via the pyyoutube.Client class.

You can initialize it with api key, to get public data.

from pyyoutube import Client\n\ncli = Client(api_key=\"your api key\")\n

If you want to update your channel data. or upload video. You need initialize with access token, Or do auth flow.

from pyyoutube import Client\n\ncli = Client(access_token=\"Access Token with permissions\")\n
from pyyoutube import Client\n\ncli = Client(client_id=\"ID for app\", client_secret=\"Secret for app\")\n# Get authorization url\ncli.get_authorize_url()\n# ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=id&redirect_uri=https%3A%2F%2Flocalhost%2F&scope=scope&state=PyYouTube&access_type=offline&prompt=select_account', 'PyYouTube')\n# Click url and give permissions.\n# Copy the redirected url.\ncli.generate_access_token(authorization_response=\"redirected url\")\n# AccessToken(access_token='token', expires_in=3599, token_type='Bearer')\n
"},{"location":"usage/work-with-client/#from-client_secret","title":"from client_secret","text":"

Only web and some installed type client_secrets are supported.

The fields client_id and client_secret must be set.

If the field redirect_uris has 1 or more values set, the Client.DEFAULT_REDIRECT_URI will be set to the first entrie.

from pyyoutube import Client\n\nfile_path = \"path/to/client_secret.json\"\ncli = Client(client_secret_path=file_path)\n\n# Then go through auth flow descriped above\n

Once initialize client. Then you can operate API to get data.

"},{"location":"usage/work-with-client/#usage","title":"Usage","text":""},{"location":"usage/work-with-client/#channel-resource","title":"Channel Resource","text":"

The API supports the following methods for channels resources:

  • list: Returns a collection of zero or more channel resources that match the request criteria.
  • update: Updates a channel's metadata. Note that this method currently only supports updates to the channel resource's brandingSettings and invideoPromotion objects and their child properties
"},{"location":"usage/work-with-client/#list-channel-data","title":"List channel data","text":"
resp = cli.channels.list(channel_id=\"UC_x5XG1OV2P6uZZ5FSM9Ttw\")\n# ChannelListResponse(kind='youtube#channelListResponse')\nprint(resp.items)\n# [Channel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw')]\n
"},{"location":"usage/work-with-client/#update-channel-metadata","title":"update channel metadata","text":"
import pyyoutube.models as mds\n\nbody = mds.Channel(\n    id=\"channel id\",\n    brandingSettings=mds.ChannelBrandingSetting(\n        image=mds.ChannelBrandingSettingImage(\n            bannerExternalUrl=\"new banner url\"\n        )\n    )\n)\n\nchannel = cli.channels.update(\n    part=\"brandingSettings\",\n    body=body\n)\nprint(channel.brandingSettings.image.bannerExternalUrl)\n# 'https://yt3.googleusercontent.com/AegVxoIusdXEmsJ9j3bcJR3zuImOd6TngNw58iJAP0AOAXCnb1xHPcuEDOQC8J85SCZvt5i8A_g'\n
"},{"location":"usage/work-with-client/#video-resource","title":"Video Resource","text":"

The API supports the following methods for videos resources.

"},{"location":"usage/work-with-client/#getrating","title":"getRating","text":"

Retrieves the ratings that the authorized user gave to a list of specified videos.

resp = cli.videos.get_rating(video_id=\"Z56Jmr9Z34Q\")\n\nprint(resp.items)\n# [VideoRatingItem(videoId='Z56Jmr9Z34Q', rating='none')]\n
"},{"location":"usage/work-with-client/#list","title":"list","text":"

Returns a list of videos that match the API request parameters.

resp = cli.videos.list(video_id=\"Z56Jmr9Z34Q\")\n\nprint(resp.items)\n# [Video(kind='youtube#video', id='Z56Jmr9Z34Q')]\n
"},{"location":"usage/work-with-client/#insert","title":"insert","text":"

Uploads a video to YouTube and optionally sets the video's metadata.

import pyyoutube.models as mds\nfrom pyyoutube.media import Media\n\nbody = mds.Video(\n    snippet=mds.VideoSnippet(\n        title=\"video title\",\n        description=\"video description\"\n    )\n)\n\nmedia = Media(filename=\"video.mp4\")\n\nupload = cli.videos.insert(\n    body=body,\n    media=media,\n    parts=[\"snippet\"],\n    notify_subscribers=True\n)\n\nvideo_body = None\n\nwhile video_body is None:\n    status, video_body = upload.next_chunk()\n    if status:\n        print(f\"Upload progress: {status.progress()}\")\n\nprint(video_body)\n# {\"kind\": \"youtube#video\", \"etag\": \"17W46NjVxoxtaoh1E6GmbQ2hv5c\",....}\n
"},{"location":"usage/work-with-client/#update","title":"update","text":"

Updates a video's metadata.

import pyyoutube.models as mds\n\nbody = mds.Video(\n    id=\"fTK1Jj6QlDw\",\n    snippet=mds.VideoSnippet(\n        title=\"What a nice day\",\n        description=\"Blue sky with cloud. updated.\",\n        categoryId=\"1\",\n    )\n)\n\nresp = cli.videos.update(\n    parts=[\"snippet\"],\n    body=body,\n    return_json=True,\n)\nprint(resp)\n# {\"kind\": \"youtube#video\", \"etag\": \"BQUtovVd0TBJwC5S8-Pu-dK_I6s\", \"id\": \"fTK1Jj6QlDw\", \"snippet\": {\"publishedAt\": \"2022-12-15T03:45:16Z\", \"channelId\": \"UCa-vrCLQHviTOVnEKDOdetQ\", \"title\": \"What a nice day\", \"description\": \"Blue sky with cloud. updated.\", \"thumbnails\": {\"default\": {\"url\": \"https://i.ytimg.com/vi/fTK1Jj6QlDw/default.jpg\", \"width\": 120, \"height\": 90}, \"medium\": {\"url\": \"https://i.ytimg.com/vi/fTK1Jj6QlDw/mqdefault.jpg\", \"width\": 320, \"height\": 180}, \"high\": {\"url\": \"https://i.ytimg.com/vi/fTK1Jj6QlDw/hqdefault.jpg\", \"width\": 480, \"height\": 360}, \"standard\": {\"url\": \"https://i.ytimg.com/vi/fTK1Jj6QlDw/sddefault.jpg\", \"width\": 640, \"height\": 480}, \"maxres\": {\"url\": \"https://i.ytimg.com/vi/fTK1Jj6QlDw/maxresdefault.jpg\", \"width\": 1280, \"height\": 720}}, \"channelTitle\": \"ikaros data\", \"categoryId\": \"1\", \"liveBroadcastContent\": \"none\", \"localized\": {\"title\": \"What a nice day\", \"description\": \"Blue sky with cloud. updated.\"}, \"defaultAudioLanguage\": \"en-US\"}}\n
"},{"location":"usage/work-with-client/#delete","title":"delete","text":"

Deletes a YouTube video.

cli.videos.delete(video_id=\"fTK1Jj6QlDw\")\n# True\n
"},{"location":"usage/work-with-client/#rate","title":"rate","text":"

Add a like or dislike rating to a video or remove a rating from a video.

cli.videos.rate(video_id=\"fTK1Jj6QlDw\", rating=\"like\")\n# True\n
"},{"location":"usage/work-with-client/#reportabuse","title":"reportAbuse","text":"

Report a video for containing abusive content.

import pyyoutube.models as mds\n\nbody = mds.VideoReportAbuse(\n    videoId=\"fTK1Jj6QlDw\",\n    reasonId=\"32\"\n)\ncli.videos.report_abuse(body=body)\n# True\n
"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..bbe1675d --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,43 @@ + + + + https://sns-sdks.github.io/python-youtube/ + 2024-04-30 + daily + + + https://sns-sdks.github.io/python-youtube/CHANGELOG/ + 2024-04-30 + daily + + + https://sns-sdks.github.io/python-youtube/authorization/ + 2024-04-30 + daily + + + https://sns-sdks.github.io/python-youtube/getting_started/ + 2024-04-30 + daily + + + https://sns-sdks.github.io/python-youtube/installation/ + 2024-04-30 + daily + + + https://sns-sdks.github.io/python-youtube/introduce-new-structure/ + 2024-04-30 + daily + + + https://sns-sdks.github.io/python-youtube/usage/work-with-api/ + 2024-04-30 + daily + + + https://sns-sdks.github.io/python-youtube/usage/work-with-client/ + 2024-04-30 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 00000000..104a914e Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/usage/work-with-api/index.html b/usage/work-with-api/index.html new file mode 100644 index 00000000..0fa45a0d --- /dev/null +++ b/usage/work-with-api/index.html @@ -0,0 +1,1308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Work With `Api` - Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Work with Api

+
+

Tips

+

This is previous version to operate YouTube DATA API.

+

We recommend using the latest version of methods to operate YouTube DATA API.

+
+

The API is exposed via the pyyoutube.Api class.

+

INSTANTIATE

+

There provide two method to create instance the pyyoutube.Api.

+

You can just initialize with an api key.

+
>>> from pyyoutube import Api
+
+>>> api = Api(api_key="your api key")
+
+

If you want to get some authorization data. you need to initialize with access token.

+
>>> from pyyoutube import Api
+
+>>> api = Api(access_token='your api key')
+
+

You can read the docs to see how to get an access token.

+

Or you can ask for user to do oauth flow:

+
>>> from pyyoutube import Api
+
+>>> api = Api(client_id="client key", client_secret="client secret")
+# Get authorization url
+>>> api.get_authorization_url()
+# ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=id&redirect_uri=https%3A%2F%2Flocalhost%2F&scope=scope&state=PyYouTube&access_type=offline&prompt=select_account', 'PyYouTube')
+# user to do
+# copy the response url
+>>> api.generate_access_token(authorization_response="link for response")
+# AccessToken(access_token='token', expires_in=3599, token_type='Bearer')
+
+

Usage

+

Now you can use the instance to get data from YouTube.

+

CHANNEL DATA

+

The library provides several ways to get channel's data.

+

If a channel is not found, the property items will return with blank list.

+

You can use channel id:

+
>>> channel_by_id = api.get_channel_info(channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw")
+>>> channel_by_id.items
+[Channel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw')]
+>>> channel_by_id.items[0].to_dict()
+{'kind': 'youtube#channel',
+ 'etag': '"j6xRRd8dTPVVptg711_CSPADRfg/AW8QEqbNRoIJv9KuzCIg0CG6aJA"',
+ 'id': 'UC_x5XG1OV2P6uZZ5FSM9Ttw',
+ 'snippet': {'title': 'Google Developers',
+  'description': 'The Google Developers channel features talks from events, educational series, best practices, tips, and the latest updates across our products and platforms.',
+  'customUrl': 'googlecode',
+  'publishedAt': '2007-08-23T00:34:43.000Z',
+  'thumbnails': {'default': {'url': 'https://yt3.ggpht.com/a/AGF-l78iFtAxyRZcUBzG91kbKMES19z-zGW5KT20_g=s88-c-k-c0xffffffff-no-rj-mo',
+    'width': 88,
+    'height': 88},
+   'medium': {'url': 'https://yt3.ggpht.com/a/AGF-l78iFtAxyRZcUBzG91kbKMES19z-zGW5KT20_g=s240-c-k-c0xffffffff-no-rj-mo',
+    'width': 240,
+    'height': 240},
+   'high': {'url': 'https://yt3.ggpht.com/a/AGF-l78iFtAxyRZcUBzG91kbKMES19z-zGW5KT20_g=s800-c-k-c0xffffffff-no-rj-mo',
+    'width': 800,
+    'height': 800},
+   'standard': None,
+   'maxres': None},
+  'defaultLanguage': None,
+  'localized': {'title': 'Google Developers',
+   'description': 'The Google Developers channel features talks from events, educational series, best practices, tips, and the latest updates across our products and platforms.'},
+  'country': 'US'},
+  ...
+  }
+
+

You can pass a channel id with comma-separated id string or a list, tuple or set of ids to get multiple channels. +Many methods also provide this functionality.

+

with ids:

+
>>> channel_by_ids = api.get_channel_info(channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw,UCa-vrCLQHviTOVnEKDOdetQ")
+>>> channel_by_ids.items
+[Channel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw'),
+ Channel(kind='youtube#channel', id='UCa-vrCLQHviTOVnEKDOdetQ')]
+
+

You can also use channel name:

+
>>> channel_by_username = api.get_channel_info(for_username="GoogleDevelopers")
+>>> channel_by_username.items[0]
+Channel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw')
+
+

If you have authorized, you can get your channels:

+
>>> channel_by_mine = api_with_authorization.get_channel_info(mine=True)
+>>> channel_by_mine.items[0]
+Channel(kind='youtube#channel', id='UCa-vrCLQHviTOVnEKDOdetQ')
+
+
+

Tips

+

To get your channel, you must do authorization first, otherwise you will get an error.

+
+

PLAYLIST

+

There are methods to get playlists by playlist id, channel id or get your own playlists.

+

Get playlists by id:

+
>>> playlists_by_id = api.get_playlist_by_id(playlist_id="PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw")
+>>> playlists_by_id.items
+[Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw')]
+
+

Get playlists by channel (If you want to get all playlists for the target channel's , just provide the +parameter count=None):

+
>>> playlists_by_channel = api.get_playlists(channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw")
+>>> playlists_by_channel.items
+[Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw'),
+ Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIJO83u2UmyC8ud41AvUnhgj'),
+ Playlist(kind='youtube#playlist', id='PLOU2XLYxmsILfV1LiUhDjbh1jkFjQWrYB'),
+ Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIKNr3Wfhm8o0TSojW7hEPPY'),
+ Playlist(kind='youtube#playlist', id='PLOU2XLYxmsIJ8ItHmK4bRlY4GCzMgXLAJ')]
+
+

Get your playlists(this requires authorization):

+
>>> playlists_by_mine = api.get_playlists(mine=True)
+
+

PLAYLIST ITEM

+

Similarly, you can get playlist items by playlist item id or playlist id.

+

Get playlist items by id:

+
>>> playlist_item_by_id = api.get_playlist_item_by_id(playlist_item_id="UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA"
+...     "1c28wZkF3d2ZUdy41NkI0NEY2RDEwNTU3Q0M2")
+
+>>> playlist_item_by_id.items
+[PlaylistItem(kind='youtube#playlistItem', id='UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA1c28wZkF3d2ZUdy41NkI0NEY2RDEwNTU3Q0M2')]
+
+

Get playlist items by playlist id (If you want to get target playlist all items, just provide the +parameter count=None):

+
>>> playlist_item_by_playlist = api.get_playlist_items(playlist_id="PLOU2XLYxmsIKpaV8h0AGE05so0fAwwfTw", count=2)
+
+>>> playlist_item_by_playlist.items
+[PlaylistItem(kind='youtube#playlistItem', id='UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA1c28wZkF3d2ZUdy41NkI0NEY2RDEwNTU3Q0M2'),
+ PlaylistItem(kind='youtube#playlistItem', id='UExPVTJYTFl4bXNJS3BhVjhoMEFHRTA1c28wZkF3d2ZUdy4yODlGNEE0NkRGMEEzMEQy')]
+>>> playlist_item_by_id.items[0].snippet.resourceId
+ResourceId(kind='youtube#video', videoId='CvTApw9X8aA')
+
+

VIDEO

+

You can get a video's information by several methods.

+

Get videos by video id(s):

+
>>> video_by_id = api.get_video_by_id(video_id="CvTApw9X8aA")
+
+>>> video_by_id
+VideoListResponse(kind='youtube#videoListResponse')
+
+>>> video_by_id.items
+[Video(kind='youtube#video', id='CvTApw9X8aA')]
+
+

Get videos by chart (If you want to get all videos, just provide the parameter count=None):

+
>>> video_by_chart = api.get_videos_by_chart(chart="mostPopular", region_code="US", count=2)
+
+>>> video_by_chart.items
+[Video(kind='youtube#video', id='RwnN2FVaHmw'),
+ Video(kind='youtube#video', id='hDeuSfo_Ys0')]
+
+

Get videos by your rating (this requires authorization, also if you want to get all videos, just provide the +parameter count=None):

+
>>> videos_by_rating = api.get_videos_by_myrating(rating="like", count=2)
+
+

COMMENT THREAD

+

You can get comment thread information by id or some filter.

+

Get comment thread by id(s):

+
>>> ct_by_id = api.get_comment_thread_by_id(comment_thread_id='Ugz097FRhsQy5CVhAjp4AaABAg,UgzhytyP79_Pwa
+... Dd4UB4AaABAg')
+
+>>> ct_by_id.items
+[CommentThread(kind='youtube#commentThread', id='Ugz097FRhsQy5CVhAjp4AaABAg'),
+ CommentThread(kind='youtube#commentThread', id='UgzhytyP79_PwaDd4UB4AaABAg')]
+
+

Get all comment threads related to a channel (including comment threads for the channel's video, also if you want to get +all comment threads, just provide the parameter count=None):

+
>>> ct_by_all = api.get_comment_threads(all_to_channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw", count=2)
+
+>>> ct_by_all.items
+[CommentThread(kind='youtube#commentThread', id='UgwlB_Cza9WtzUWahYN4AaABAg'),
+ CommentThread(kind='youtube#commentThread', id='UgyvoQJ2LsxCBwGEpMB4AaABAg')]
+
+

Get comment threads only for the channel (If you want to get all comment threads, just provide the +parameter count=None):

+
>>> ct_by_channel = api.get_comment_threads(channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw", count=2)
+
+>>> ct_by_channel.items
+[CommentThread(kind='youtube#commentThread', id='UgyUBI0HsgL9emxcZpR4AaABAg'),
+ CommentThread(kind='youtube#commentThread', id='Ugzi3lkqDPfIOirGFLh4AaABAg')]
+
+

Get comment threads only for the video (If you want to get all comment threads, just provide the +parameter count=None):

+
>>> ct_by_video = api.get_comment_threads(video_id="D-lhorsDlUQ", count=2)
+
+>>> ct_by_video.items
+[CommentThread(kind='youtube#commentThread', id='UgydxWWoeA7F1OdqypJ4AaABAg'),
+ CommentThread(kind='youtube#commentThread', id='UgxKREWxIgDrw8w2e_Z4AaABAg')]
+
+

COMMENT

+

You can get comment information by id or use the top-level comment id to get replies.

+
+

Tips

+

The reply has the same structure as a comment.

+
+

Get comments by id(s):

+
>>> comment_by_id = api.get_comment_by_id(comment_id='UgxKREWxIgDrw8w2e_Z4AaABAg,UgyrVQaFfEdvaSzstj14AaABAg')
+
+>>> comment_by_id.items
+[Comment(kind='youtube#comment', id='UgxKREWxIgDrw8w2e_Z4AaABAg', snippet=CommentSnippet(authorDisplayName='Hieu Nguyen', likeCount=0)),
+ Comment(kind='youtube#comment', id='UgyrVQaFfEdvaSzstj14AaABAg', snippet=CommentSnippet(authorDisplayName='Mani Kanta', likeCount=0))]
+
+

Get replies by comment id (If you want to get all comments, just provide the parameter count=None):

+
>>> comment_by_parent = api.get_comments(parent_id="UgwYjZXfNCUTKPq9CZp4AaABAg")
+>>> comment_by_parent.items
+[Comment(kind='youtube#comment', id='UgwYjZXfNCUTKPq9CZp4AaABAg.8yxhlQJogG18yz_cXK9Kcj', snippet=CommentSnippet(authorDisplayName='Marlon López', likeCount=0))]
+
+

VIDEO CATEGORY

+

You can get video category with id or region.

+

Get video categories with id(s):

+
>>> video_category_by_id = api.get_video_categories(category_id="17,18")
+
+>>> video_category_by_id.items
+[VideoCategory(kind='youtube#videoCategory', id='17'),
+ VideoCategory(kind='youtube#videoCategory', id='18')]
+
+

Get video categories with region code:

+
>>> video_categories_by_region = api.get_video_categories(region_code="US")
+
+>>> video_categories_by_region.items
+[VideoCategory(kind='youtube#videoCategory', id='1'),
+ VideoCategory(kind='youtube#videoCategory', id='2'),
+ VideoCategory(kind='youtube#videoCategory', id='10'),
+ VideoCategory(kind='youtube#videoCategory', id='15'),
+ ...]
+
+

SUBSCRIPTIONS

+

You can get subscription information by id, by point channel, or your own.

+
+

Tips

+

If you want to get the subscriptions not set to public, you need do authorization first and get the access token. +You can see the demo A demo for get my subscription.

+
+

To get subscription info by id(s), this needs your token to have the permission for the subscriptions belonging to a +channel or user:

+
>>> r = api.get_subscription_by_id(
+...         subscription_id=[
+...             "zqShTXi-2-Tx7TtwQqhCBwViE_j9IEgnmRmPnqJljxo",
+...             "zqShTXi-2-Rya5uUxEp3ZsPI3fZrFQnSXNQCwvHBGGo"])
+>>> r
+SubscriptionListResponse(kind='youtube#subscriptionListResponse')
+>>> r.items
+[Subscription(kind='youtube#subscription', id='zqShTXi-2-Tx7TtwQqhCBwViE_j9IEgnmRmPnqJljxo', snippet=SubscriptionSnippet(title='PyCon 2015', description='')),
+ Subscription(kind='youtube#subscription', id='zqShTXi-2-Rya5uUxEp3ZsPI3fZrFQnSXNQCwvHBGGo', snippet=SubscriptionSnippet(title='ikaros-life', description='This is a test channel.'))]
+
+

Get your own subscriptions, this need you do authorization first or give the authorized access token:

+
>>> r = api.get_subscription_by_me(
+...         mine=True,
+...         parts=["id", "snippet"],
+...         count=2
+... )
+>>> r
+SubscriptionListResponse(kind='youtube#subscriptionListResponse')
+>>> r.items
+[Subscription(kind='youtube#subscription', id='zqShTXi-2-Tx7TtwQqhCBwtJ-Aho6DZeutqZiP4Q79Q', snippet=SubscriptionSnippet(title='Next Day Video', description='')),
+ Subscription(kind='youtube#subscription', id='zqShTXi-2-Tx7TtwQqhCBwViE_j9IEgnmRmPnqJljxo', snippet=SubscriptionSnippet(title='PyCon 2015', description=''))]
+
+

Get public channel's subscriptions:

+
>>> r = api.get_subscription_by_channel(
+...      channel_id="UCAuUUnT6oDeKwE6v1NGQxug",
+...      parts="id,snippet",
+...      count=2
+... )
+>>> r
+SubscriptionListResponse(kind='youtube#subscriptionListResponse')
+>>> r.items
+[Subscription(kind='youtube#subscription', id='FMP3Mleijt-52zZDGkHtR5KhwkvCcdQKWWWIA1j5eGc', snippet=SubscriptionSnippet(title='TEDx Talks', description="TEDx is an international community that organizes TED-style events anywhere and everywhere -- celebrating locally-driven ideas and elevating them to a global stage. TEDx events are produced independently of TED conferences, each event curates speakers on their own, but based on TED's format and rules.\n\nFor more information on using TED for commercial purposes (e.g. employee learning, in a film, or in an online course), please submit a media request using the link below.")),
+ Subscription(kind='youtube#subscription', id='FMP3Mleijt_ZKvy5M-HhRlsqI4wXY7VmP5g8lvmRhVU', snippet=SubscriptionSnippet(title='TED Residency', description='The TED Residency program is an incubator for breakthrough ideas. It is free and open to all via a semi-annual competitive application. Those chosen as TED Residents spend four months at TED headquarters in New York City, working on their idea. Selection criteria include the strength of their idea, their character, and their ability to bring a fresh perspective and positive contribution to the diverse TED community.'))]
+
+

ACTIVITIES

+

You can get activities by channel id. You can also get your own activities after you have completed authorization.

+

Get public channel activities:

+
>>> r = api.get_activities_by_channel(channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw", count=2)
+>>> r
+ActivityListResponse(kind='youtube#activityListResponse')
+>>> r.items
+[Activity(kind='youtube#activity', id='MTUxNTc3NzM2MDAyODIxOTQxNDM0NjAwMA==', snippet=ActivitySnippet(title='2019 Year in Review - The Developer Show', description='Here to bring you the latest developer news from across Google this year is Developer Advocate Timothy Jordan. In this last week of the year, we’re taking a look back at some of the coolest and biggest announcements we covered in 2019! \n\nFollow Google Developers on Instagram → https://goo.gle/googledevs\n\nWatch more #DevShow → https://goo.gle/GDevShow\nSubscribe to Google Developers → https://goo.gle/developers')),
+ Activity(kind='youtube#activity', id='MTUxNTc3MTI4NzIzODIxOTQxNDM0NzI4MA==', snippet=ActivitySnippet(title='GDE Promo - Lara Martin', description='Meet Lara Martin, a Flutter/Dart Google Developers Expert and get inspired by her journey. Watch now for a preview of her story! #GDESpotlights #IncludedWithGoogle\n\nLearn about the GDE program → https://goo.gle/2qWOvAy\n\nGoogle Developers Experts → https://goo.gle/GDE\nSubscribe to Google Developers → https://goo.gle/developers'))]
+
+

Get your activities:

+
>>> r = api_with_token.get_activities_by_me()
+>>> r.items
+[Activity(kind='youtube#activity', id='MTUxNTc0OTk2MjI3NDE0MjYwMDY1NjAwODA=', snippet=ActivitySnippet(title='华山日出', description='冷冷的山头')),
+ Activity(kind='youtube#activity', id='MTUxNTc0OTk1OTAyNDE0MjYwMDY1NTc2NDg=', snippet=ActivitySnippet(title='海上日出', description='美美美'))]
+
+

Get your video captions:

+
>>> r = api.get_captions_by_video(video_id="oHR3wURdJ94", parts=["id", "snippet"])
+>>> r
+CaptionListResponse(kind='youtube#captionListResponse')
+>>> r.items
+[Caption(kind='youtube#caption', id='SwPOvp0r7kd9ttt_XhcHdZthMwXG7Z0I', snippet=CaptionSnippet(videoId='oHR3wURdJ94', lastUpdated='2020-01-14T09:40:49.981Z')),
+ Caption(kind='youtube#caption', id='fPMuDm722CIRcUAT3NTPQHQZJZJxt39kU7JvrHk8Kzs=', snippet=CaptionSnippet(videoId='oHR3wURdJ94', lastUpdated='2020-01-14T09:39:46.991Z'))]
+
+

If you already have caption id(s), you can get video caption by id(s):

+
>>> r = api.get_captions_by_video(video_id="oHR3wURdJ94", parts=["id", "snippet"], caption_id="SwPOvp0r7kd9ttt_XhcHdZthMwXG7Z0I")
+>>> r
+CaptionListResponse(kind='youtube#captionListResponse')
+>>> r.items
+[Caption(kind='youtube#caption', id='SwPOvp0r7kd9ttt_XhcHdZthMwXG7Z0I', snippet=CaptionSnippet(videoId='oHR3wURdJ94', lastUpdated='2020-01-14T09:40:49.981Z'))]
+
+

CHANNEL SECTIONS

+

You can get channel sections by self id or belonged channel id or your own channel.

+

Get channel sections by channel id:

+
>>> r = api.get_channel_sections_by_channel(channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw")
+>>>> r
+ChannelSectionResponse(kind='youtube#channelSectionListResponse')
+>>> r.items
+[ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.e-Fk7vMPqLE'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.B8DTd9ZXJqM'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.MfvRjkWLxgk'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.fEjJOXRoWwg'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.PvTmxDBxtLs'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.pmcIOsL7s98'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.c3r3vYf9uD0'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.ZJpkBl-mXfM'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.9_wU0qhEPR8'),
+ ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.npYvuMz0_es')]
+
+

Get authorized user's channel sections:

+
>>> r = api.get_channel_sections_by_channel(mine=True)
+>>> r.items
+[ChannelSection(kind='youtube#channelSection', id='UCa-vrCLQHviTOVnEKDOdetQ.jNQXAC9IVRw'),
+ ChannelSection(kind='youtube#channelSection', id='UCa-vrCLQHviTOVnEKDOdetQ.LeAltgu_pbM'),
+ ChannelSection(kind='youtube#channelSection', id='UCa-vrCLQHviTOVnEKDOdetQ.nGzAI5pLbMY')]
+
+

Get channel section detail info by id:

+
>>> r = api.get_channel_section_by_id(section_id="UC_x5XG1OV2P6uZZ5FSM9Ttw.e-Fk7vMPqLE")
+>>> r
+ChannelSectionResponse(kind='youtube#channelSectionListResponse')
+>>> r1.items
+[ChannelSection(kind='youtube#channelSection', id='UC_x5XG1OV2P6uZZ5FSM9Ttw.e-Fk7vMPqLE')]
+
+

I18N RESOURCE

+

You can get a list of content regions that the YouTube website supports:

+
>>> r = api.get_i18n_regions(parts=["snippet"])
+>>> r.items
+[I18nRegion(kind='youtube#i18nRegion', id='DZ', snippet=I18nRegionSnippet(gl='DZ', name='Algeria')),
+ I18nRegion(kind='youtube#i18nRegion', id='AR', snippet=I18nRegionSnippet(gl='AR', name='Argentina')),
+ I18nRegion(kind='youtube#i18nRegion', id='AU', snippet=I18nRegionSnippet(gl='AU', name='Australia'))
+ ...]
+
+

You can get a list of application languages that the YouTube website supports:

+
>>> r = api.get_i18n_languages(parts=["snippet"])
+>>> r.items
+[I18nLanguage(kind='youtube#i18nLanguage', id='af', snippet=I18nLanguageSnippet(hl='af', name='Afrikaans')),
+ I18nLanguage(kind='youtube#i18nLanguage', id='az', snippet=I18nLanguageSnippet(hl='az', name='Azerbaijani')),
+ I18nLanguage(kind='youtube#i18nLanguage', id='id', snippet=I18nLanguageSnippet(hl='id', name='Indonesian')),
+ ...]
+
+

MEMBER

+

The API request must be authorized by the channel owner.

+

You can retrieve a list of members (formerly known as "sponsors") for a channel:

+
>>> r = api_with_token.get_members(parts=["snippet"])
+>>> r.items
+[MemberListResponse(kind='youtube#memberListResponse'),
+ MemberListResponse(kind='youtube#memberListResponse')]
+
+

MEMBERSHIP LEVEL

+

The API request must be authorized by the channel owner.

+

You can retrieve a list membership levels for a channel:

+
>>> r = api_with_token.get_membership_levels(parts=["snippet"])
+>>> r.items
+[MembershipsLevelListResponse(kind='youtube#membershipsLevelListResponse'),
+ MembershipsLevelListResponse(kind='youtube#membershipsLevelListResponse')]
+
+

VIDEO ABUSE REPORT REASON

+

You can retrieve a list of reasons that can be used to report abusive videos:

+
>>> r = api_with_token.get_video_abuse_report_reason(parts=["snippet"])
+>>> r.items
+[VideoAbuseReportReason(kind='youtube#videoAbuseReportReason'),
+ VideoAbuseReportReason(kind='youtube#videoAbuseReportReason')]
+
+ +

You can use those methods to search the video,playlist,channel data. For more info, you can see +the Search Request Docs.

+

You can search different type of resource with keywords:

+
>>> r = api.search_by_keywords(q="surfing", search_type=["channel","video", "playlist"], count=5, limit=5)
+>>> r.items
+[SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult')]
+
+

You can search your app send videos:

+
>>> r = api_with_token.search_by_developer(q="news", count=1)
+>>> r.items
+[SearchResult(kind='youtube#searchResult')]
+
+

You can search your videos:

+
>>> r = api_with_token.search_by_mine(q="news", count=1)
+>>> r.items
+[SearchResult(kind='youtube#searchResult')]
+
+

Or you can build your request using the search method:

+
>>> r = api.search(
+...     location="21.5922529, -158.1147114",
+...     location_radius="10mi",
+...     q="surfing",
+...     parts=["snippet"],
+...     count=5,
+...     published_after="2020-02-01T00:00:00Z",
+...     published_before="2020-03-01T00:00:00Z",
+...     safe_search="moderate",
+...     search_type="video")
+>>> r.items
+[SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult')]
+
+>>> r = api.search(
+...     event_type="live",
+...     q="news",
+...     count=3,
+...     parts=["snippet"],
+...     search_type="video",
+...     topic_id="/m/09s1f",
+...     order="viewCount")
+>>> r.items
+[SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult'),
+ SearchResult(kind='youtube#searchResult')]
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/usage/work-with-client/index.html b/usage/work-with-client/index.html new file mode 100644 index 00000000..e9fc77b5 --- /dev/null +++ b/usage/work-with-client/index.html @@ -0,0 +1,1044 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Work With `Client` - Python-Youtube Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + +
+
+ + + +
+
+
+ + + + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + + +

Work with Client

+

We have refactored the project code to support more methods and improve code usability.

+

And new structure like follows.

+

structure-uml

+

In this structure, we identify each entity as a class of resources and perform operations on the resources.

+

INSTANTIATE

+

Client is exposed via the pyyoutube.Client class.

+

You can initialize it with api key, to get public data.

+
from pyyoutube import Client
+
+cli = Client(api_key="your api key")
+
+

If you want to update your channel data. or upload video. You need initialize with access token, Or do auth flow.

+
from pyyoutube import Client
+
+cli = Client(access_token="Access Token with permissions")
+
+
from pyyoutube import Client
+
+cli = Client(client_id="ID for app", client_secret="Secret for app")
+# Get authorization url
+cli.get_authorize_url()
+# ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=id&redirect_uri=https%3A%2F%2Flocalhost%2F&scope=scope&state=PyYouTube&access_type=offline&prompt=select_account', 'PyYouTube')
+# Click url and give permissions.
+# Copy the redirected url.
+cli.generate_access_token(authorization_response="redirected url")
+# AccessToken(access_token='token', expires_in=3599, token_type='Bearer')
+
+

from client_secret

+

Only web and some installed type client_secrets are supported.

+

The fields client_id and client_secret must be set.

+

If the field redirect_uris has 1 or more values set, the Client.DEFAULT_REDIRECT_URI will be set to the first entrie.

+
from pyyoutube import Client
+
+file_path = "path/to/client_secret.json"
+cli = Client(client_secret_path=file_path)
+
+# Then go through auth flow descriped above
+
+

Once initialize client. Then you can operate API to get data.

+

Usage

+

Channel Resource

+

The API supports the following methods for channels resources:

+
    +
  • list: Returns a collection of zero or more channel resources that match the request criteria.
  • +
  • update: Updates a channel's metadata. Note that this method currently only supports updates to the channel resource's + brandingSettings and invideoPromotion objects and their child properties
  • +
+

List channel data

+
resp = cli.channels.list(channel_id="UC_x5XG1OV2P6uZZ5FSM9Ttw")
+# ChannelListResponse(kind='youtube#channelListResponse')
+print(resp.items)
+# [Channel(kind='youtube#channel', id='UC_x5XG1OV2P6uZZ5FSM9Ttw')]
+
+

update channel metadata

+
import pyyoutube.models as mds
+
+body = mds.Channel(
+    id="channel id",
+    brandingSettings=mds.ChannelBrandingSetting(
+        image=mds.ChannelBrandingSettingImage(
+            bannerExternalUrl="new banner url"
+        )
+    )
+)
+
+channel = cli.channels.update(
+    part="brandingSettings",
+    body=body
+)
+print(channel.brandingSettings.image.bannerExternalUrl)
+# 'https://yt3.googleusercontent.com/AegVxoIusdXEmsJ9j3bcJR3zuImOd6TngNw58iJAP0AOAXCnb1xHPcuEDOQC8J85SCZvt5i8A_g'
+
+

Video Resource

+

The API supports the following methods for videos resources.

+

getRating

+

Retrieves the ratings that the authorized user gave to a list of specified videos.

+
resp = cli.videos.get_rating(video_id="Z56Jmr9Z34Q")
+
+print(resp.items)
+# [VideoRatingItem(videoId='Z56Jmr9Z34Q', rating='none')]
+
+

list

+

Returns a list of videos that match the API request parameters.

+
resp = cli.videos.list(video_id="Z56Jmr9Z34Q")
+
+print(resp.items)
+# [Video(kind='youtube#video', id='Z56Jmr9Z34Q')]
+
+

insert

+

Uploads a video to YouTube and optionally sets the video's metadata.

+
import pyyoutube.models as mds
+from pyyoutube.media import Media
+
+body = mds.Video(
+    snippet=mds.VideoSnippet(
+        title="video title",
+        description="video description"
+    )
+)
+
+media = Media(filename="video.mp4")
+
+upload = cli.videos.insert(
+    body=body,
+    media=media,
+    parts=["snippet"],
+    notify_subscribers=True
+)
+
+video_body = None
+
+while video_body is None:
+    status, video_body = upload.next_chunk()
+    if status:
+        print(f"Upload progress: {status.progress()}")
+
+print(video_body)
+# {"kind": "youtube#video", "etag": "17W46NjVxoxtaoh1E6GmbQ2hv5c",....}
+
+

update

+

Updates a video's metadata.

+
import pyyoutube.models as mds
+
+body = mds.Video(
+    id="fTK1Jj6QlDw",
+    snippet=mds.VideoSnippet(
+        title="What a nice day",
+        description="Blue sky with cloud. updated.",
+        categoryId="1",
+    )
+)
+
+resp = cli.videos.update(
+    parts=["snippet"],
+    body=body,
+    return_json=True,
+)
+print(resp)
+# {"kind": "youtube#video", "etag": "BQUtovVd0TBJwC5S8-Pu-dK_I6s", "id": "fTK1Jj6QlDw", "snippet": {"publishedAt": "2022-12-15T03:45:16Z", "channelId": "UCa-vrCLQHviTOVnEKDOdetQ", "title": "What a nice day", "description": "Blue sky with cloud. updated.", "thumbnails": {"default": {"url": "https://i.ytimg.com/vi/fTK1Jj6QlDw/default.jpg", "width": 120, "height": 90}, "medium": {"url": "https://i.ytimg.com/vi/fTK1Jj6QlDw/mqdefault.jpg", "width": 320, "height": 180}, "high": {"url": "https://i.ytimg.com/vi/fTK1Jj6QlDw/hqdefault.jpg", "width": 480, "height": 360}, "standard": {"url": "https://i.ytimg.com/vi/fTK1Jj6QlDw/sddefault.jpg", "width": 640, "height": 480}, "maxres": {"url": "https://i.ytimg.com/vi/fTK1Jj6QlDw/maxresdefault.jpg", "width": 1280, "height": 720}}, "channelTitle": "ikaros data", "categoryId": "1", "liveBroadcastContent": "none", "localized": {"title": "What a nice day", "description": "Blue sky with cloud. updated."}, "defaultAudioLanguage": "en-US"}}
+
+

delete

+

Deletes a YouTube video.

+
cli.videos.delete(video_id="fTK1Jj6QlDw")
+# True
+
+

rate

+

Add a like or dislike rating to a video or remove a rating from a video.

+
cli.videos.rate(video_id="fTK1Jj6QlDw", rating="like")
+# True
+
+

reportAbuse

+

Report a video for containing abusive content.

+
import pyyoutube.models as mds
+
+body = mds.VideoReportAbuse(
+    videoId="fTK1Jj6QlDw",
+    reasonId="32"
+)
+cli.videos.report_abuse(body=body)
+# True
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file