November 9, 2026 · 4 min read
How to Get YouTube Transcripts in Ruby (and Rails)
In short
Fetch YouTube transcripts in Ruby with Net::HTTP and JSON from the standard library: timestamped segments, SRT and VTT files, translation, and Rails jobs.
Ruby's standard library is enough: Net::HTTP and JSON fetch any public video's transcript from the TranscriptYT YouTube Transcript API, with no gem to install and no YouTube scraping on your server.
Fetch a transcript
Create a free key in the dashboard (100 transcripts, no card) and export it as TRANSCRIPTYT_KEY.
require "net/http"
require "json"
def get_transcript(video, **params)
uri = URI("https://transcript-yt.com/v1/transcript")
uri.query = URI.encode_www_form(url: video, **params)
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch("TRANSCRIPTYT_KEY")}"
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true, read_timeout: 120) { |http| http.request(req) }
return res.body if res.is_a?(Net::HTTPSuccess) && params[:format]
data = JSON.parse(res.body)
raise "#{data["error"]["code"]}: #{data["error"]["message"]}" unless res.is_a?(Net::HTTPSuccess)
data
end
t = get_transcript("https://youtu.be/5f3Pn-N6yLc")
puts t["title"]
t["segments"].first(3).each { |s| printf("%7.1fs %s\n", s["start"], s["text"]) }Subtitle files and translation
Pass format: "srt" (or vtt, text, csv, md) and the helper above returns the file body. Add translate_to: with a language code to translate into one of 150+ languages with the timings kept.
File.write("captions.es.srt", get_transcript("5f3Pn-N6yLc", format: "srt", translate_to: "es"))Errors and retries
BLOCKED, RATE_LIMITED, and UPSTREAM_ERROR are temporary; retry them with backoff (retry_on in Active Job does this). VIDEO_UNAVAILABLE, NO_CAPTIONS, and LANGUAGE_NOT_AVAILABLE are final, and a 402 means you're out of credits. Failed requests are never billed. Every code is in the docs.
Common questions
How do I get a YouTube transcript in Ruby?
Send a GET request to https://transcript-yt.com/v1/transcript with the video URL as the url parameter and your key in the Authorization header, then JSON.parse the body.
Can I fetch transcripts in a Rails background job?
Yes. Put the request in an Active Job or Sidekiq job and store the text on your model. Retry the job on BLOCKED, RATE_LIMITED, and UPSTREAM_ERROR.
Does it work with Faraday or HTTParty?
Yes. It's one GET request with a Bearer header, so any HTTP client works.