youtube-transcript-nodejs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +337 -0
  3. package/dist/cjs/api/InnerTubeClient.js +236 -0
  4. package/dist/cjs/api/InnerTubeClient.js.map +1 -0
  5. package/dist/cjs/api/YouTubeTranscriptApi.js +160 -0
  6. package/dist/cjs/api/YouTubeTranscriptApi.js.map +1 -0
  7. package/dist/cjs/api/fetchStrategies.js +51 -0
  8. package/dist/cjs/api/fetchStrategies.js.map +1 -0
  9. package/dist/cjs/config/constants.js +34 -0
  10. package/dist/cjs/config/constants.js.map +1 -0
  11. package/dist/cjs/config/innerTubeContext.js +82 -0
  12. package/dist/cjs/config/innerTubeContext.js.map +1 -0
  13. package/dist/cjs/errors/BotDetected.js +20 -0
  14. package/dist/cjs/errors/BotDetected.js.map +1 -0
  15. package/dist/cjs/errors/FailedToCreateConsentCookie.js +17 -0
  16. package/dist/cjs/errors/FailedToCreateConsentCookie.js.map +1 -0
  17. package/dist/cjs/errors/InvalidVideoId.js +16 -0
  18. package/dist/cjs/errors/InvalidVideoId.js.map +1 -0
  19. package/dist/cjs/errors/IpBlocked.js +17 -0
  20. package/dist/cjs/errors/IpBlocked.js.map +1 -0
  21. package/dist/cjs/errors/NoTranscriptFound.js +23 -0
  22. package/dist/cjs/errors/NoTranscriptFound.js.map +1 -0
  23. package/dist/cjs/errors/NotTranslatable.js +15 -0
  24. package/dist/cjs/errors/NotTranslatable.js.map +1 -0
  25. package/dist/cjs/errors/PoTokenRequired.js +18 -0
  26. package/dist/cjs/errors/PoTokenRequired.js.map +1 -0
  27. package/dist/cjs/errors/TooManyRequests.js +19 -0
  28. package/dist/cjs/errors/TooManyRequests.js.map +1 -0
  29. package/dist/cjs/errors/TranscriptsDisabled.js +15 -0
  30. package/dist/cjs/errors/TranscriptsDisabled.js.map +1 -0
  31. package/dist/cjs/errors/TranslationLanguageNotAvailable.js +16 -0
  32. package/dist/cjs/errors/TranslationLanguageNotAvailable.js.map +1 -0
  33. package/dist/cjs/errors/VideoUnavailable.js +15 -0
  34. package/dist/cjs/errors/VideoUnavailable.js.map +1 -0
  35. package/dist/cjs/errors/VideoUnplayable.js +22 -0
  36. package/dist/cjs/errors/VideoUnplayable.js.map +1 -0
  37. package/dist/cjs/errors/YouTubeDataUnparsable.js +15 -0
  38. package/dist/cjs/errors/YouTubeDataUnparsable.js.map +1 -0
  39. package/dist/cjs/errors/YouTubeRequestFailed.js +18 -0
  40. package/dist/cjs/errors/YouTubeRequestFailed.js.map +1 -0
  41. package/dist/cjs/errors/YouTubeTranscriptError.js +19 -0
  42. package/dist/cjs/errors/YouTubeTranscriptError.js.map +1 -0
  43. package/dist/cjs/errors/index.js +34 -0
  44. package/dist/cjs/errors/index.js.map +1 -0
  45. package/dist/cjs/formatters/Formatter.js +3 -0
  46. package/dist/cjs/formatters/Formatter.js.map +1 -0
  47. package/dist/cjs/formatters/JSONFormatter.js +24 -0
  48. package/dist/cjs/formatters/JSONFormatter.js.map +1 -0
  49. package/dist/cjs/formatters/PrettyPrintFormatter.js +26 -0
  50. package/dist/cjs/formatters/PrettyPrintFormatter.js.map +1 -0
  51. package/dist/cjs/formatters/SRTFormatter.js +39 -0
  52. package/dist/cjs/formatters/SRTFormatter.js.map +1 -0
  53. package/dist/cjs/formatters/TextFormatter.js +20 -0
  54. package/dist/cjs/formatters/TextFormatter.js.map +1 -0
  55. package/dist/cjs/formatters/WebVTTFormatter.js +39 -0
  56. package/dist/cjs/formatters/WebVTTFormatter.js.map +1 -0
  57. package/dist/cjs/formatters/base.js +61 -0
  58. package/dist/cjs/formatters/base.js.map +1 -0
  59. package/dist/cjs/formatters/index.js +19 -0
  60. package/dist/cjs/formatters/index.js.map +1 -0
  61. package/dist/cjs/http/cookieJar.js +91 -0
  62. package/dist/cjs/http/cookieJar.js.map +1 -0
  63. package/dist/cjs/http/httpClient.js +228 -0
  64. package/dist/cjs/http/httpClient.js.map +1 -0
  65. package/dist/cjs/index.js +50 -0
  66. package/dist/cjs/index.js.map +1 -0
  67. package/dist/cjs/models/FetchedTranscript.js +80 -0
  68. package/dist/cjs/models/FetchedTranscript.js.map +1 -0
  69. package/dist/cjs/models/FetchedTranscriptSnippet.js +29 -0
  70. package/dist/cjs/models/FetchedTranscriptSnippet.js.map +1 -0
  71. package/dist/cjs/models/FormattedTranscript.js +3 -0
  72. package/dist/cjs/models/FormattedTranscript.js.map +1 -0
  73. package/dist/cjs/models/Transcript.js +75 -0
  74. package/dist/cjs/models/Transcript.js.map +1 -0
  75. package/dist/cjs/models/TranscriptList.js +84 -0
  76. package/dist/cjs/models/TranscriptList.js.map +1 -0
  77. package/dist/cjs/models/TranscriptMetadata.js +3 -0
  78. package/dist/cjs/models/TranscriptMetadata.js.map +1 -0
  79. package/dist/cjs/models/TranslationLanguage.js +3 -0
  80. package/dist/cjs/models/TranslationLanguage.js.map +1 -0
  81. package/dist/cjs/models/index.js +13 -0
  82. package/dist/cjs/models/index.js.map +1 -0
  83. package/dist/cjs/package.json +1 -0
  84. package/dist/cjs/parsers/captionTrackParser.js +96 -0
  85. package/dist/cjs/parsers/captionTrackParser.js.map +1 -0
  86. package/dist/cjs/parsers/videoIdParser.js +65 -0
  87. package/dist/cjs/parsers/videoIdParser.js.map +1 -0
  88. package/dist/cjs/parsers/watchHtmlParser.js +78 -0
  89. package/dist/cjs/parsers/watchHtmlParser.js.map +1 -0
  90. package/dist/cjs/parsers/xmlTranscriptParser.js +84 -0
  91. package/dist/cjs/parsers/xmlTranscriptParser.js.map +1 -0
  92. package/dist/cjs/potoken/AutoPoTokenProvider.js +203 -0
  93. package/dist/cjs/potoken/AutoPoTokenProvider.js.map +1 -0
  94. package/dist/cjs/potoken/HttpPoTokenProvider.js +105 -0
  95. package/dist/cjs/potoken/HttpPoTokenProvider.js.map +1 -0
  96. package/dist/cjs/potoken/NoopPoTokenProvider.js +18 -0
  97. package/dist/cjs/potoken/NoopPoTokenProvider.js.map +1 -0
  98. package/dist/cjs/potoken/baseScriptCache.js +41 -0
  99. package/dist/cjs/potoken/baseScriptCache.js.map +1 -0
  100. package/dist/cjs/potoken/index.js +14 -0
  101. package/dist/cjs/potoken/index.js.map +1 -0
  102. package/dist/cjs/potoken/types.js +10 -0
  103. package/dist/cjs/potoken/types.js.map +1 -0
  104. package/dist/cjs/util/htmlSanitizer.js +77 -0
  105. package/dist/cjs/util/htmlSanitizer.js.map +1 -0
  106. package/dist/cjs/util/proxyUrl.js +42 -0
  107. package/dist/cjs/util/proxyUrl.js.map +1 -0
  108. package/dist/cjs/util/retry.js +65 -0
  109. package/dist/cjs/util/retry.js.map +1 -0
  110. package/dist/esm/api/InnerTubeClient.d.ts +61 -0
  111. package/dist/esm/api/InnerTubeClient.d.ts.map +1 -0
  112. package/dist/esm/api/InnerTubeClient.js +198 -0
  113. package/dist/esm/api/InnerTubeClient.js.map +1 -0
  114. package/dist/esm/api/YouTubeTranscriptApi.d.ts +88 -0
  115. package/dist/esm/api/YouTubeTranscriptApi.d.ts.map +1 -0
  116. package/dist/esm/api/YouTubeTranscriptApi.js +157 -0
  117. package/dist/esm/api/YouTubeTranscriptApi.js.map +1 -0
  118. package/dist/esm/api/fetchStrategies.d.ts +20 -0
  119. package/dist/esm/api/fetchStrategies.d.ts.map +1 -0
  120. package/dist/esm/api/fetchStrategies.js +48 -0
  121. package/dist/esm/api/fetchStrategies.js.map +1 -0
  122. package/dist/esm/config/constants.d.ts +30 -0
  123. package/dist/esm/config/constants.d.ts.map +1 -0
  124. package/dist/esm/config/constants.js +31 -0
  125. package/dist/esm/config/constants.js.map +1 -0
  126. package/dist/esm/config/innerTubeContext.d.ts +47 -0
  127. package/dist/esm/config/innerTubeContext.d.ts.map +1 -0
  128. package/dist/esm/config/innerTubeContext.js +77 -0
  129. package/dist/esm/config/innerTubeContext.js.map +1 -0
  130. package/dist/esm/errors/BotDetected.d.ts +13 -0
  131. package/dist/esm/errors/BotDetected.d.ts.map +1 -0
  132. package/dist/esm/errors/BotDetected.js +16 -0
  133. package/dist/esm/errors/BotDetected.js.map +1 -0
  134. package/dist/esm/errors/FailedToCreateConsentCookie.d.ts +10 -0
  135. package/dist/esm/errors/FailedToCreateConsentCookie.d.ts.map +1 -0
  136. package/dist/esm/errors/FailedToCreateConsentCookie.js +13 -0
  137. package/dist/esm/errors/FailedToCreateConsentCookie.js.map +1 -0
  138. package/dist/esm/errors/InvalidVideoId.d.ts +9 -0
  139. package/dist/esm/errors/InvalidVideoId.d.ts.map +1 -0
  140. package/dist/esm/errors/InvalidVideoId.js +12 -0
  141. package/dist/esm/errors/InvalidVideoId.js.map +1 -0
  142. package/dist/esm/errors/IpBlocked.d.ts +10 -0
  143. package/dist/esm/errors/IpBlocked.d.ts.map +1 -0
  144. package/dist/esm/errors/IpBlocked.js +13 -0
  145. package/dist/esm/errors/IpBlocked.js.map +1 -0
  146. package/dist/esm/errors/NoTranscriptFound.d.ts +19 -0
  147. package/dist/esm/errors/NoTranscriptFound.d.ts.map +1 -0
  148. package/dist/esm/errors/NoTranscriptFound.js +19 -0
  149. package/dist/esm/errors/NoTranscriptFound.js.map +1 -0
  150. package/dist/esm/errors/NotTranslatable.d.ts +9 -0
  151. package/dist/esm/errors/NotTranslatable.d.ts.map +1 -0
  152. package/dist/esm/errors/NotTranslatable.js +11 -0
  153. package/dist/esm/errors/NotTranslatable.js.map +1 -0
  154. package/dist/esm/errors/PoTokenRequired.d.ts +10 -0
  155. package/dist/esm/errors/PoTokenRequired.d.ts.map +1 -0
  156. package/dist/esm/errors/PoTokenRequired.js +14 -0
  157. package/dist/esm/errors/PoTokenRequired.js.map +1 -0
  158. package/dist/esm/errors/TooManyRequests.d.ts +12 -0
  159. package/dist/esm/errors/TooManyRequests.d.ts.map +1 -0
  160. package/dist/esm/errors/TooManyRequests.js +15 -0
  161. package/dist/esm/errors/TooManyRequests.js.map +1 -0
  162. package/dist/esm/errors/TranscriptsDisabled.d.ts +9 -0
  163. package/dist/esm/errors/TranscriptsDisabled.d.ts.map +1 -0
  164. package/dist/esm/errors/TranscriptsDisabled.js +11 -0
  165. package/dist/esm/errors/TranscriptsDisabled.js.map +1 -0
  166. package/dist/esm/errors/TranslationLanguageNotAvailable.d.ts +9 -0
  167. package/dist/esm/errors/TranslationLanguageNotAvailable.d.ts.map +1 -0
  168. package/dist/esm/errors/TranslationLanguageNotAvailable.js +12 -0
  169. package/dist/esm/errors/TranslationLanguageNotAvailable.js.map +1 -0
  170. package/dist/esm/errors/VideoUnavailable.d.ts +9 -0
  171. package/dist/esm/errors/VideoUnavailable.d.ts.map +1 -0
  172. package/dist/esm/errors/VideoUnavailable.js +11 -0
  173. package/dist/esm/errors/VideoUnavailable.js.map +1 -0
  174. package/dist/esm/errors/VideoUnplayable.d.ts +12 -0
  175. package/dist/esm/errors/VideoUnplayable.d.ts.map +1 -0
  176. package/dist/esm/errors/VideoUnplayable.js +18 -0
  177. package/dist/esm/errors/VideoUnplayable.js.map +1 -0
  178. package/dist/esm/errors/YouTubeDataUnparsable.d.ts +9 -0
  179. package/dist/esm/errors/YouTubeDataUnparsable.d.ts.map +1 -0
  180. package/dist/esm/errors/YouTubeDataUnparsable.js +11 -0
  181. package/dist/esm/errors/YouTubeDataUnparsable.js.map +1 -0
  182. package/dist/esm/errors/YouTubeRequestFailed.d.ts +10 -0
  183. package/dist/esm/errors/YouTubeRequestFailed.d.ts.map +1 -0
  184. package/dist/esm/errors/YouTubeRequestFailed.js +14 -0
  185. package/dist/esm/errors/YouTubeRequestFailed.js.map +1 -0
  186. package/dist/esm/errors/YouTubeTranscriptError.d.ts +10 -0
  187. package/dist/esm/errors/YouTubeTranscriptError.d.ts.map +1 -0
  188. package/dist/esm/errors/YouTubeTranscriptError.js +15 -0
  189. package/dist/esm/errors/YouTubeTranscriptError.js.map +1 -0
  190. package/dist/esm/errors/index.d.ts +17 -0
  191. package/dist/esm/errors/index.d.ts.map +1 -0
  192. package/dist/esm/errors/index.js +16 -0
  193. package/dist/esm/errors/index.js.map +1 -0
  194. package/dist/esm/formatters/Formatter.d.ts +33 -0
  195. package/dist/esm/formatters/Formatter.d.ts.map +1 -0
  196. package/dist/esm/formatters/Formatter.js +2 -0
  197. package/dist/esm/formatters/Formatter.js.map +1 -0
  198. package/dist/esm/formatters/JSONFormatter.d.ts +10 -0
  199. package/dist/esm/formatters/JSONFormatter.d.ts.map +1 -0
  200. package/dist/esm/formatters/JSONFormatter.js +20 -0
  201. package/dist/esm/formatters/JSONFormatter.js.map +1 -0
  202. package/dist/esm/formatters/PrettyPrintFormatter.d.ts +15 -0
  203. package/dist/esm/formatters/PrettyPrintFormatter.d.ts.map +1 -0
  204. package/dist/esm/formatters/PrettyPrintFormatter.js +22 -0
  205. package/dist/esm/formatters/PrettyPrintFormatter.js.map +1 -0
  206. package/dist/esm/formatters/SRTFormatter.d.ts +22 -0
  207. package/dist/esm/formatters/SRTFormatter.d.ts.map +1 -0
  208. package/dist/esm/formatters/SRTFormatter.js +35 -0
  209. package/dist/esm/formatters/SRTFormatter.js.map +1 -0
  210. package/dist/esm/formatters/TextFormatter.d.ts +10 -0
  211. package/dist/esm/formatters/TextFormatter.d.ts.map +1 -0
  212. package/dist/esm/formatters/TextFormatter.js +16 -0
  213. package/dist/esm/formatters/TextFormatter.js.map +1 -0
  214. package/dist/esm/formatters/WebVTTFormatter.d.ts +22 -0
  215. package/dist/esm/formatters/WebVTTFormatter.d.ts.map +1 -0
  216. package/dist/esm/formatters/WebVTTFormatter.js +35 -0
  217. package/dist/esm/formatters/WebVTTFormatter.js.map +1 -0
  218. package/dist/esm/formatters/base.d.ts +25 -0
  219. package/dist/esm/formatters/base.d.ts.map +1 -0
  220. package/dist/esm/formatters/base.js +55 -0
  221. package/dist/esm/formatters/base.js.map +1 -0
  222. package/dist/esm/formatters/index.d.ts +8 -0
  223. package/dist/esm/formatters/index.d.ts.map +1 -0
  224. package/dist/esm/formatters/index.js +7 -0
  225. package/dist/esm/formatters/index.js.map +1 -0
  226. package/dist/esm/http/cookieJar.d.ts +39 -0
  227. package/dist/esm/http/cookieJar.d.ts.map +1 -0
  228. package/dist/esm/http/cookieJar.js +87 -0
  229. package/dist/esm/http/cookieJar.js.map +1 -0
  230. package/dist/esm/http/httpClient.d.ts +88 -0
  231. package/dist/esm/http/httpClient.d.ts.map +1 -0
  232. package/dist/esm/http/httpClient.js +191 -0
  233. package/dist/esm/http/httpClient.js.map +1 -0
  234. package/dist/esm/index.d.ts +19 -0
  235. package/dist/esm/index.d.ts.map +1 -0
  236. package/dist/esm/index.js +14 -0
  237. package/dist/esm/index.js.map +1 -0
  238. package/dist/esm/models/FetchedTranscript.d.ts +49 -0
  239. package/dist/esm/models/FetchedTranscript.d.ts.map +1 -0
  240. package/dist/esm/models/FetchedTranscript.js +76 -0
  241. package/dist/esm/models/FetchedTranscript.js.map +1 -0
  242. package/dist/esm/models/FetchedTranscriptSnippet.d.ts +15 -0
  243. package/dist/esm/models/FetchedTranscriptSnippet.d.ts.map +1 -0
  244. package/dist/esm/models/FetchedTranscriptSnippet.js +25 -0
  245. package/dist/esm/models/FetchedTranscriptSnippet.js.map +1 -0
  246. package/dist/esm/models/FormattedTranscript.d.ts +9 -0
  247. package/dist/esm/models/FormattedTranscript.d.ts.map +1 -0
  248. package/dist/esm/models/FormattedTranscript.js +2 -0
  249. package/dist/esm/models/FormattedTranscript.js.map +1 -0
  250. package/dist/esm/models/Transcript.d.ts +36 -0
  251. package/dist/esm/models/Transcript.d.ts.map +1 -0
  252. package/dist/esm/models/Transcript.js +71 -0
  253. package/dist/esm/models/Transcript.js.map +1 -0
  254. package/dist/esm/models/TranscriptList.d.ts +48 -0
  255. package/dist/esm/models/TranscriptList.d.ts.map +1 -0
  256. package/dist/esm/models/TranscriptList.js +79 -0
  257. package/dist/esm/models/TranscriptList.js.map +1 -0
  258. package/dist/esm/models/TranscriptMetadata.d.ts +10 -0
  259. package/dist/esm/models/TranscriptMetadata.d.ts.map +1 -0
  260. package/dist/esm/models/TranscriptMetadata.js +2 -0
  261. package/dist/esm/models/TranscriptMetadata.js.map +1 -0
  262. package/dist/esm/models/TranslationLanguage.d.ts +8 -0
  263. package/dist/esm/models/TranslationLanguage.d.ts.map +1 -0
  264. package/dist/esm/models/TranslationLanguage.js +2 -0
  265. package/dist/esm/models/TranslationLanguage.js.map +1 -0
  266. package/dist/esm/models/index.d.ts +8 -0
  267. package/dist/esm/models/index.d.ts.map +1 -0
  268. package/dist/esm/models/index.js +5 -0
  269. package/dist/esm/models/index.js.map +1 -0
  270. package/dist/esm/package.json +1 -0
  271. package/dist/esm/parsers/captionTrackParser.d.ts +29 -0
  272. package/dist/esm/parsers/captionTrackParser.d.ts.map +1 -0
  273. package/dist/esm/parsers/captionTrackParser.js +91 -0
  274. package/dist/esm/parsers/captionTrackParser.js.map +1 -0
  275. package/dist/esm/parsers/videoIdParser.d.ts +11 -0
  276. package/dist/esm/parsers/videoIdParser.d.ts.map +1 -0
  277. package/dist/esm/parsers/videoIdParser.js +61 -0
  278. package/dist/esm/parsers/videoIdParser.js.map +1 -0
  279. package/dist/esm/parsers/watchHtmlParser.d.ts +33 -0
  280. package/dist/esm/parsers/watchHtmlParser.d.ts.map +1 -0
  281. package/dist/esm/parsers/watchHtmlParser.js +70 -0
  282. package/dist/esm/parsers/watchHtmlParser.js.map +1 -0
  283. package/dist/esm/parsers/xmlTranscriptParser.d.ts +17 -0
  284. package/dist/esm/parsers/xmlTranscriptParser.d.ts.map +1 -0
  285. package/dist/esm/parsers/xmlTranscriptParser.js +81 -0
  286. package/dist/esm/parsers/xmlTranscriptParser.js.map +1 -0
  287. package/dist/esm/potoken/AutoPoTokenProvider.d.ts +28 -0
  288. package/dist/esm/potoken/AutoPoTokenProvider.d.ts.map +1 -0
  289. package/dist/esm/potoken/AutoPoTokenProvider.js +166 -0
  290. package/dist/esm/potoken/AutoPoTokenProvider.js.map +1 -0
  291. package/dist/esm/potoken/HttpPoTokenProvider.d.ts +41 -0
  292. package/dist/esm/potoken/HttpPoTokenProvider.d.ts.map +1 -0
  293. package/dist/esm/potoken/HttpPoTokenProvider.js +101 -0
  294. package/dist/esm/potoken/HttpPoTokenProvider.js.map +1 -0
  295. package/dist/esm/potoken/NoopPoTokenProvider.d.ts +12 -0
  296. package/dist/esm/potoken/NoopPoTokenProvider.d.ts.map +1 -0
  297. package/dist/esm/potoken/NoopPoTokenProvider.js +14 -0
  298. package/dist/esm/potoken/NoopPoTokenProvider.js.map +1 -0
  299. package/dist/esm/potoken/baseScriptCache.d.ts +28 -0
  300. package/dist/esm/potoken/baseScriptCache.d.ts.map +1 -0
  301. package/dist/esm/potoken/baseScriptCache.js +37 -0
  302. package/dist/esm/potoken/baseScriptCache.js.map +1 -0
  303. package/dist/esm/potoken/index.d.ts +10 -0
  304. package/dist/esm/potoken/index.d.ts.map +1 -0
  305. package/dist/esm/potoken/index.js +6 -0
  306. package/dist/esm/potoken/index.js.map +1 -0
  307. package/dist/esm/potoken/types.d.ts +40 -0
  308. package/dist/esm/potoken/types.d.ts.map +1 -0
  309. package/dist/esm/potoken/types.js +7 -0
  310. package/dist/esm/potoken/types.js.map +1 -0
  311. package/dist/esm/util/htmlSanitizer.d.ts +21 -0
  312. package/dist/esm/util/htmlSanitizer.d.ts.map +1 -0
  313. package/dist/esm/util/htmlSanitizer.js +69 -0
  314. package/dist/esm/util/htmlSanitizer.js.map +1 -0
  315. package/dist/esm/util/proxyUrl.d.ts +22 -0
  316. package/dist/esm/util/proxyUrl.d.ts.map +1 -0
  317. package/dist/esm/util/proxyUrl.js +39 -0
  318. package/dist/esm/util/proxyUrl.js.map +1 -0
  319. package/dist/esm/util/retry.d.ts +37 -0
  320. package/dist/esm/util/retry.d.ts.map +1 -0
  321. package/dist/esm/util/retry.js +60 -0
  322. package/dist/esm/util/retry.js.map +1 -0
  323. package/package.json +111 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 youtube-transcript-plus contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,337 @@
1
+ # youtube-transcript-nodejs
2
+
3
+ A complete Node.js + TypeScript port of [jdepoix/youtube-transcript-api](https://github.com/jdepoix/youtube-transcript-api), with optional self-contained PoToken generation.
4
+
5
+ [![Node ≥ 20](https://img.shields.io/badge/node-%E2%89%A520-339933)]() [![License MIT](https://img.shields.io/badge/license-MIT-blue)]() [![Tests 182 passing](https://img.shields.io/badge/tests-182_passing-brightgreen)]() [![Live verified](https://img.shields.io/badge/live_verified-4%2F4-success)]()
6
+
7
+ ## Why this port?
8
+
9
+ The Python library is the de-facto standard for YouTube transcript fetching. It works by issuing requests via the **ANDROID InnerTube client**, which historically is not subject to YouTube's PoToken bot-detection. Node.js has lacked a 1:1 equivalent:
10
+
11
+ | Capability | jdepoix Python | `youtube-transcript` | `youtube-transcript-nodejs` (this) |
12
+ |---|---|---|---|
13
+ | `fetch` transcript | ✅ | ✅ | ✅ |
14
+ | `list` all tracks | ✅ | ❌ | ✅ |
15
+ | `translate` to another language | ✅ | ❌ | ✅ |
16
+ | `translationLanguages` enumeration | ✅ | ❌ | ✅ |
17
+ | 5 formatters (SRT/VTT/JSON/Text/Pretty) | ✅ | ❌ | ✅ |
18
+ | Full error hierarchy | ✅ | ⚠️ | ✅ |
19
+ | Proxy / custom cookies / headers | ✅ | ❌ | ✅ |
20
+ | Self-contained PoToken | ❌ | ❌ | ✅ (opt-in) |
21
+ | EU CONSENT cookie handling | ❌ | ❌ | ✅ |
22
+ | TypeScript-first, ESM + CJS dual | ❌ | ⚠️ | ✅ |
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ npm install youtube-transcript-nodejs
28
+ ```
29
+
30
+ Requires **Node.js ≥ 20** (for native `fetch` and stable ESM).
31
+
32
+ The core API has **no runtime dependencies** beyond `he` and `fast-xml-parser`. Optional peer dependencies (`bgutils-js`, `undici`) are only loaded when used:
33
+
34
+ - `bgutils-js` — only required for `AutoPoTokenProvider`
35
+ - `undici` — only required when you pass `proxyConfig`
36
+
37
+ ## Quick Start
38
+
39
+ ```ts
40
+ import { YouTubeTranscriptApi } from 'youtube-transcript-nodejs';
41
+
42
+ const api = new YouTubeTranscriptApi();
43
+ const transcript = await api.fetch('dQw4w9WgXcQ');
44
+ console.log(transcript.toText().content.slice(0, 200));
45
+ ```
46
+
47
+ ## Test Results
48
+
49
+ End-to-end verified against the live YouTube API (test video: `dQw4w9WgXcQ`).
50
+
51
+ ### Unit tests — 182 / 182 passing
52
+
53
+ ```
54
+ ✓ test/unit/parsers/captionTrackParser.test.ts (12 tests)
55
+ ✓ test/unit/config/config.test.ts (15 tests)
56
+ ✓ test/unit/util/util.test.ts (19 tests)
57
+ ✓ test/unit/formatters/formatters.test.ts (22 tests)
58
+ ✓ test/unit/http/httpClient.test.ts ( 8 tests)
59
+ ✓ test/unit/errors/errors.test.ts (21 tests)
60
+ ✓ test/unit/api/innerTubeClient.test.ts (18 tests)
61
+ ✓ test/unit/potoken/potoken.test.ts (11 tests)
62
+ ✓ test/unit/parsers/watchHtmlParser.test.ts (11 tests)
63
+ ✓ test/unit/parsers/videoIdParser.test.ts (12 tests)
64
+ ✓ test/unit/api/youTubeTranscriptApi.test.ts (11 tests)
65
+ ✓ test/unit/http/cookieJar.test.ts ( 7 tests)
66
+ ✓ test/unit/parsers/xmlTranscriptParser.test.ts ( 7 tests)
67
+ ✓ test/unit/potoken/autoPoTokenProvider.test.ts ( 6 tests)
68
+ ✓ test/unit/smoke.test.ts ( 1 test)
69
+ ```
70
+
71
+ ### Live integration tests — 4 / 4 passing
72
+
73
+ Run with `RUN_LIVE=1 YT_TEST_VIDEO_ID=dQw4w9WgXcQ npm run test:live`.
74
+
75
+ ```
76
+ ✓ live: fetch > fetches the transcript for a public video (6.4 s)
77
+ ✓ live: list > returns at least one transcript track (5.9 s)
78
+ ✓ live: translate > translates to a target language (11.7 s)
79
+ ✓ live: translationLanguages > returns many translation targets (6.6 s)
80
+ ```
81
+
82
+ ### Build & lint
83
+
84
+ ```
85
+ ✓ npm run lint — 0 errors, 0 warnings (ESLint strict)
86
+ ✓ npm run typecheck — tsc --noEmit (strict mode)
87
+ ✓ npm run build — ESM (dist/esm) + CJS (dist/cjs) dual publish
88
+ ✓ npm pack --dry-run — 76.4 KB tarball
89
+ ```
90
+
91
+ ### Real output (sanitized)
92
+
93
+ ```text
94
+ $ npx tsx examples/basic.ts
95
+ Video: dQw4w9WgXcQ
96
+ Language: English (en)
97
+ Generated: false
98
+ Snippets: 61
99
+ ---
100
+ [♪♪♪]
101
+ ♪ We're no strangers to love ♪
102
+ ♪ You know the rules
103
+ and so do I ♪
104
+ ♪ A full commitment's
105
+ what I'm thinking of ♪
106
+ ♪ You wouldn't get this
107
+ from any other guy ♪
108
+
109
+ $ npx tsx examples/list.ts
110
+ Video: dQw4w9WgXcQ
111
+ Manually created: en, de-DE, ja, pt-BR, es-419
112
+ Auto-generated: en
113
+ Translation targets: 18
114
+ Selected: English (en, manual)
115
+ First cue: [1.36s] [♪♪♪]
116
+
117
+ $ head -10 dQw4w9WgXcQ.es.srt # after `tsx examples/translate.ts`
118
+ 1
119
+ 00:00:01,360 --> 00:00:03,040
120
+ [♪♪♪]
121
+
122
+ 2
123
+ 00:00:18,640 --> 00:00:21,880
124
+ ♪ No somos extraños al amor ♪
125
+ ```
126
+
127
+ ## API Reference
128
+
129
+ ### `new YouTubeTranscriptApi(config?)`
130
+
131
+ ```ts
132
+ interface YouTubeTranscriptApiConfig {
133
+ /** HTTP proxy URL. Triggers undici dynamic import. */
134
+ proxyConfig?: { url: string };
135
+ /** Pre-set cookies (e.g. CONSENT for EU users). */
136
+ cookies?: Array<{ name: string; value: string; domain?: string; path?: string }>;
137
+ /** Default headers added to every request. */
138
+ headers?: Record<string, string>;
139
+ /** Replace the default NoopPoTokenProvider. */
140
+ poTokenProvider?: PoTokenProvider;
141
+ /** When true, ANDROID failures automatically retry via WEB + PoToken. */
142
+ poTokenFallback?: boolean;
143
+ /** Custom User-Agent override. */
144
+ userAgent?: string;
145
+ /** Custom fetch implementation (testing). */
146
+ fetchImpl?: typeof fetch;
147
+ }
148
+ ```
149
+
150
+ ### Methods
151
+
152
+ #### `api.fetch(videoId, opts?): Promise<FetchedTranscript>`
153
+
154
+ ```ts
155
+ const t = await api.fetch('dQw4w9WgXcQ', {
156
+ languages: ['en', 'en-US', 'en-GB'], // ordered preference
157
+ preserveFormatting: false, // keep <i>/<b> tags
158
+ });
159
+ ```
160
+
161
+ #### `api.list(videoId): Promise<TranscriptList>`
162
+
163
+ ```ts
164
+ const list = await api.list('dQw4w9WgXcQ');
165
+ console.log('manual:', list.manuallyCreatedTranscripts.map(t => t.languageCode));
166
+ console.log('auto:', list.generatedTranscripts.map(t => t.languageCode));
167
+
168
+ const en = list.findTranscript(['en', 'en-US']);
169
+ const data = await en.fetch();
170
+ ```
171
+
172
+ #### `api.translate(videoId, targetLang, opts?): Promise<FetchedTranscript>`
173
+
174
+ ```ts
175
+ const zh = await api.translate('dQw4w9WgXcQ', 'zh-Hans');
176
+ console.log(zh.toSRT().content);
177
+ ```
178
+
179
+ #### `api.translationLanguages(videoId, sourceLang): Promise<TranslationLanguage[]>`
180
+
181
+ ```ts
182
+ const langs = await api.translationLanguages('dQw4w9WgXcQ', 'en');
183
+ // [{ languageCode: 'es', languageName: 'Spanish' }, ...]
184
+ ```
185
+
186
+ #### `api.setPoTokenProvider(provider): void`
187
+
188
+ Swap the provider at runtime.
189
+
190
+ ## Formatters
191
+
192
+ `FetchedTranscript` exposes five convenience methods plus a generic `format()`:
193
+
194
+ ```ts
195
+ t.toRaw(); // JSON array of { text, start, duration }
196
+ t.toText(); // Plain text, one snippet per line
197
+ t.toSRT(); // SRT subtitle format
198
+ t.toVTT(); // WebVTT subtitle format
199
+ t.toPretty(); // [HH:MM:SS.mmm] text
200
+
201
+ // Or bring your own:
202
+ import type { Formatter } from 'youtube-transcript-nodejs';
203
+ class MyCsvFormatter implements Formatter { /* ... */ }
204
+ t.format(new MyCsvFormatter());
205
+ ```
206
+
207
+ ## Errors
208
+
209
+ The package throws specific error subclasses that all extend `YouTubeTranscriptError`:
210
+
211
+ | Class | Trigger |
212
+ |---|---|
213
+ | `InvalidVideoId` | Provided id cannot be parsed (not 11 chars, not a URL). |
214
+ | `FailedToCreateConsentCookie` | EU consent gate can't be auto-handled. |
215
+ | `VideoUnavailable` | InnerTube `playabilityStatus.status === ERROR` + "This video is unavailable". |
216
+ | `VideoUnplayable` | Other unplayable status, with `reason` and `subreason` populated. |
217
+ | `TooManyRequests` | Explicit rate-limit (not normally thrown; 429 maps to `IpBlocked`). |
218
+ | `IpBlocked` | HTTP 429 or captcha gate; status code attached. |
219
+ | `BotDetected` | InnerTube reports BotGuard block (bent-quote reason). |
220
+ | `PoTokenRequired` | Caption track's `baseUrl` contains `&exp=xpe`. |
221
+ | `TranscriptsDisabled` | InnerTube returns no caption tracks. |
222
+ | `NotTranslatable` | `.translate()` on a non-translatable track. |
223
+ | `TranslationLanguageNotAvailable` | Target language not in `translationLanguages`. |
224
+ | `NoTranscriptFound` | None of the requested language codes match. |
225
+ | `YouTubeRequestFailed` | Generic HTTP failure. |
226
+ | `YouTubeDataUnparsable` | Watch HTML / InnerTube JSON couldn't be parsed. |
227
+
228
+ ```ts
229
+ import { NoTranscriptFound, BotDetected } from 'youtube-transcript-nodejs';
230
+
231
+ try {
232
+ await api.fetch(videoId);
233
+ } catch (err) {
234
+ if (err instanceof BotDetected) {
235
+ // Provide a PoToken provider or proxy
236
+ } else if (err instanceof NoTranscriptFound) {
237
+ console.log('Try different languages:', err.requestedLanguageCodes);
238
+ } else {
239
+ throw err;
240
+ }
241
+ }
242
+ ```
243
+
244
+ ## Proxy, Cookies, Headers
245
+
246
+ ```ts
247
+ const api = new YouTubeTranscriptApi({
248
+ proxyConfig: { url: 'http://user:pass@proxy.example.com:8080' },
249
+ // or: 'socks5://localhost:1080'
250
+ cookies: [
251
+ { name: 'CONSENT', value: 'YES+cb', domain: '.youtube.com' },
252
+ ],
253
+ headers: { 'X-Forwarded-For': '1.2.3.4' },
254
+ userAgent: 'MyCrawler/1.0',
255
+ });
256
+ ```
257
+
258
+ ## PoToken Support
259
+
260
+ YouTube may rate-limit or block ANDROID InnerTube on some networks. To enable automatic retry via the WEB client + PoToken:
261
+
262
+ ```ts
263
+ import { YouTubeTranscriptApi, AutoPoTokenProvider } from 'youtube-transcript-nodejs';
264
+
265
+ // 1. Self-contained (requires `npm install bgutils-js`)
266
+ const api = new YouTubeTranscriptApi({
267
+ poTokenProvider: new AutoPoTokenProvider(),
268
+ poTokenFallback: true,
269
+ });
270
+
271
+ // 2. External HTTP provider (e.g. bgutil-ytdlp-pot-provider sidecar)
272
+ import { HttpPoTokenProvider } from 'youtube-transcript-nodejs';
273
+ const api = new YouTubeTranscriptApi({
274
+ poTokenProvider: new HttpPoTokenProvider({
275
+ baseUrl: 'http://localhost:4416',
276
+ }),
277
+ poTokenFallback: true,
278
+ });
279
+
280
+ // 3. Custom — implement PoTokenProvider yourself
281
+ const myProvider: PoTokenProvider = {
282
+ async generateForVideo(videoId) {
283
+ return {
284
+ poToken: '...',
285
+ visitorData: '...',
286
+ expiresAt: new Date(Date.now() + 12 * 3600 * 1000),
287
+ };
288
+ },
289
+ };
290
+ ```
291
+
292
+ `AutoPoTokenProvider` lazy-loads `bgutils-js` at runtime. If the package is not installed, `generateForVideo()` throws `BotDetected` so the caller can surface a clear error.
293
+
294
+ ## Differences from the Python Library
295
+
296
+ | | Python | Node (this package) |
297
+ |---|---|---|
298
+ | HTTP client | `requests` | Native `fetch` (Node 18+) |
299
+ | InnerTube key extraction | regex `"INNERTUBE_API_KEY":\s*"([^"]+)"` | Same regex + 2 fallbacks |
300
+ | Default User-Agent | `python-requests/X.Y.Z` | `Mozilla/5.0 ... Chrome/124` (PoToken-friendly) |
301
+ | XML parser | `defusedxml.ElementTree` | `fast-xml-parser` for root + regex for `<text>` (preserves inline HTML) |
302
+ | Formatters | Module-level functions | Classes implementing `Formatter` interface |
303
+ | Cookies | `requests.Session` jar | Custom minimal `CookieJar` |
304
+ | Retry on 429 | `urllib3.Retry` | Exponential backoff (configurable) |
305
+ | PoToken | Passive detection only | Pluggable provider + self-contained default |
306
+
307
+ ## Limitations
308
+
309
+ - Not every video has subtitles; `TranscriptsDisabled` is expected behavior.
310
+ - YouTube may change its protocol at any time; pin a version.
311
+ - AutoPoTokenProvider depends on `bgutils-js` staying current with YouTube's botguard obfuscation.
312
+ - Live (streaming) videos are not supported.
313
+ - Region-locked videos require a proxy / cookie in the right region.
314
+ - ASR (auto-generated) captions can be inaccurate.
315
+
316
+ ## Contributing
317
+
318
+ ```bash
319
+ git clone <repo>
320
+ cd yttapi
321
+ npm install
322
+ npm run lint # ESLint
323
+ npm run typecheck # tsc --noEmit
324
+ npm test # unit tests (always runs, 182 tests)
325
+ npm run test:live # live integration tests (RUN_LIVE=1, 4 tests)
326
+ npm run build # ESM + CJS dual publish
327
+ ```
328
+
329
+ Live tests default to skipped. To exercise them:
330
+
331
+ ```bash
332
+ RUN_LIVE=1 YT_TEST_VIDEO_ID=dQw4w9WgXcQ npm run test:live
333
+ ```
334
+
335
+ ## License
336
+
337
+ MIT
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.InnerTubeClient = void 0;
37
+ exports.mapHttpStatusToError = mapHttpStatusToError;
38
+ const constants_js_1 = require("../config/constants.js");
39
+ const innerTubeContext_js_1 = require("../config/innerTubeContext.js");
40
+ const index_js_1 = require("../errors/index.js");
41
+ const watchHtmlParser_js_1 = require("../parsers/watchHtmlParser.js");
42
+ const captionTrackParser_js_1 = require("../parsers/captionTrackParser.js");
43
+ /**
44
+ * Reason sent by InnerTube when BotGuard blocks the request.
45
+ *
46
+ * NOTE: the apostrophe is a U+2019 "RIGHT SINGLE QUOTATION MARK", not
47
+ * ASCII. This is the exact string returned by YouTube.
48
+ */
49
+ const BOT_DETECT_REASON = 'Sign in to confirm you’re not a bot';
50
+ const AGE_RESTRICTED_REASON = 'This video may be inappropriate for some users.';
51
+ const VIDEO_UNAVAILABLE_REASON = 'This video is unavailable';
52
+ /**
53
+ * Thin InnerTube client implementing the ANDROID-first strategy.
54
+ *
55
+ * Mirrors the Python library's `_transcripts.TranscriptListFetcher._fetch_innertube_data`
56
+ * but with explicit client selection.
57
+ */
58
+ class InnerTubeClient {
59
+ http;
60
+ constructor(opts) {
61
+ this.http = opts.http;
62
+ }
63
+ /**
64
+ * Fetch the watch HTML for a video id, returning the raw HTML.
65
+ *
66
+ * Performs EU-consent gate handling: if the response is the consent
67
+ * page, parses out the `v` form value and retries once with the
68
+ * CONSENT cookie set.
69
+ */
70
+ async fetchWatchHtml(videoId) {
71
+ const url = constants_js_1.WATCH_URL.replace('{video_id}', videoId);
72
+ let html = await (await this.http.get(url)).text();
73
+ if ((0, watchHtmlParser_js_1.isConsentGate)(html)) {
74
+ const v = (0, watchHtmlParser_js_1.extractConsentFormValue)(html);
75
+ if (!v) {
76
+ throw new index_js_1.FailedToCreateConsentCookie(videoId);
77
+ }
78
+ // Set CONSENT cookie and re-fetch.
79
+ const cookieValue = (0, watchHtmlParser_js_1.buildConsentCookieValue)(v);
80
+ // We poke the underlying cookie jar via an extra request that
81
+ // triggers ingestion; HttpClient stores cookies from Set-Cookie
82
+ // headers. Here we simulate by setting a request header that
83
+ // YouTube recognises.
84
+ html = await (await this.http.get(url, {
85
+ headers: { Cookie: `CONSENT=${cookieValue}` },
86
+ })).text();
87
+ if ((0, watchHtmlParser_js_1.isConsentGate)(html)) {
88
+ throw new index_js_1.FailedToCreateConsentCookie(videoId);
89
+ }
90
+ }
91
+ return html;
92
+ }
93
+ /**
94
+ * Extract INNERTUBE_API_KEY from watch HTML.
95
+ */
96
+ extractApiKey(html, videoId) {
97
+ return (0, watchHtmlParser_js_1.extractInnertubeApiKey)(html, videoId);
98
+ }
99
+ /**
100
+ * Issue an InnerTube player request with the given client context.
101
+ */
102
+ async fetchPlayer(videoId, apiKey, ctx) {
103
+ const url = constants_js_1.INNERTUBE_API_URL.replace('{api_key}', apiKey);
104
+ const body = {
105
+ context: {
106
+ client: {
107
+ clientName: ctx.client.clientName,
108
+ clientVersion: ctx.client.clientVersion,
109
+ hl: ctx.client.hl,
110
+ gl: ctx.client.gl,
111
+ },
112
+ },
113
+ videoId,
114
+ };
115
+ if (ctx.client.androidSdkVersion !== undefined) {
116
+ body['context']['client'] = {
117
+ ...body['context']['client'],
118
+ androidSdkVersion: ctx.client.androidSdkVersion,
119
+ };
120
+ }
121
+ const headers = {
122
+ 'X-YouTube-Client-Name': (0, innerTubeContext_js_1.clientNameHeader)(ctx),
123
+ 'X-YouTube-Client-Version': (0, innerTubeContext_js_1.clientVersionHeader)(ctx),
124
+ };
125
+ if (ctx.client.userAgent) {
126
+ headers['User-Agent'] = ctx.client.userAgent;
127
+ }
128
+ const response = await this.http.postJson(url, body, { headers });
129
+ return response.json();
130
+ }
131
+ /**
132
+ * Validate the player response and extract caption tracks.
133
+ */
134
+ extractCaptionTracks(playerJson, videoId) {
135
+ if (typeof playerJson !== 'object' || playerJson === null) {
136
+ throw new index_js_1.YouTubeDataUnparsable(videoId, 'InnerTube response is not an object');
137
+ }
138
+ const data = playerJson;
139
+ this.assertPlayability(data['playabilityStatus'], videoId);
140
+ const captions = data['captions'];
141
+ if (typeof captions !== 'object' || captions === null) {
142
+ throw new index_js_1.TranscriptsDisabled(videoId);
143
+ }
144
+ const tracklistJson = captions['playerCaptionsTracklistRenderer'];
145
+ const parsed = (0, captionTrackParser_js_1.parseCaptionTracklist)(tracklistJson);
146
+ if (!parsed) {
147
+ throw new index_js_1.TranscriptsDisabled(videoId);
148
+ }
149
+ return {
150
+ captionTracks: parsed.captionTracks,
151
+ translationLanguages: parsed.translationLanguages ?? [],
152
+ };
153
+ }
154
+ /**
155
+ * Fetch the timedtext XML for a single caption track.
156
+ */
157
+ async fetchTranscriptXml(baseUrl, videoId) {
158
+ if (baseUrl.includes('&exp=xpe')) {
159
+ const { PoTokenRequired } = await Promise.resolve().then(() => __importStar(require('../errors/index.js')));
160
+ throw new PoTokenRequired(videoId);
161
+ }
162
+ const response = await this.http.get(baseUrl);
163
+ return response.text();
164
+ }
165
+ /**
166
+ * Append `tlang=...` to a baseUrl for translation.
167
+ */
168
+ buildTranslateUrl(baseUrl, targetLang) {
169
+ const sep = baseUrl.includes('?') ? '&' : '?';
170
+ return `${baseUrl}${sep}tlang=${encodeURIComponent(targetLang)}`;
171
+ }
172
+ assertPlayability(playabilityStatus, videoId) {
173
+ if (typeof playabilityStatus !== 'object' || playabilityStatus === null)
174
+ return;
175
+ const ps = playabilityStatus;
176
+ const status = ps['status'];
177
+ if (status === 'OK' || status === undefined)
178
+ return;
179
+ const reason = typeof ps['reason'] === 'string' ? ps['reason'] : undefined;
180
+ if (status === 'LOGIN_REQUIRED') {
181
+ if (reason === BOT_DETECT_REASON) {
182
+ throw new index_js_1.BotDetected(videoId);
183
+ }
184
+ if (reason === AGE_RESTRICTED_REASON) {
185
+ // We don't model AgeRestricted as a class; use VideoUnplayable.
186
+ throw new index_js_1.VideoUnplayable(videoId, reason, []);
187
+ }
188
+ throw new index_js_1.VideoUnplayable(videoId, reason, extractSubreasons(ps));
189
+ }
190
+ if (status === 'ERROR') {
191
+ if (reason === VIDEO_UNAVAILABLE_REASON) {
192
+ if (videoId.startsWith('http://') || videoId.startsWith('https://')) {
193
+ // URL passed in — looks like an invalid id case.
194
+ throw new index_js_1.YouTubeDataUnparsable(videoId, 'video id looks like a URL');
195
+ }
196
+ throw new index_js_1.VideoUnavailable(videoId);
197
+ }
198
+ throw new index_js_1.VideoUnplayable(videoId, reason, extractSubreasons(ps));
199
+ }
200
+ throw new index_js_1.VideoUnplayable(videoId, reason, extractSubreasons(ps));
201
+ }
202
+ }
203
+ exports.InnerTubeClient = InnerTubeClient;
204
+ function extractSubreasons(playabilityStatus) {
205
+ const errorScreen = playabilityStatus['errorScreen'];
206
+ if (typeof errorScreen !== 'object' || errorScreen === null)
207
+ return [];
208
+ const playerErr = errorScreen['playerErrorMessageRenderer'];
209
+ if (typeof playerErr !== 'object' || playerErr === null)
210
+ return [];
211
+ const subreason = playerErr['subreason'];
212
+ if (typeof subreason !== 'object' || subreason === null)
213
+ return [];
214
+ const runs = subreason['runs'];
215
+ if (!Array.isArray(runs))
216
+ return [];
217
+ const texts = [];
218
+ for (const run of runs) {
219
+ if (typeof run === 'object' && run !== null) {
220
+ const t = run['text'];
221
+ if (typeof t === 'string')
222
+ texts.push(t);
223
+ }
224
+ }
225
+ return texts;
226
+ }
227
+ /**
228
+ * Map a generic HTTP failure status (after retries) to a specific error.
229
+ */
230
+ function mapHttpStatusToError(videoId, status, statusText, url) {
231
+ if (status === 429) {
232
+ return new index_js_1.IpBlocked(videoId, status);
233
+ }
234
+ return new index_js_1.YouTubeRequestFailed(videoId, status, statusText, url);
235
+ }
236
+ //# sourceMappingURL=InnerTubeClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InnerTubeClient.js","sourceRoot":"","sources":["../../../src/api/InnerTubeClient.ts"],"names":[],"mappings":"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"}