Skip to content

Instantly share code, notes, and snippets.

@cleanhands
Created June 17, 2026 17:25
Show Gist options
  • Select an option

  • Save cleanhands/3528f0f2e109de72588efe33d6ca0af6 to your computer and use it in GitHub Desktop.

Select an option

Save cleanhands/3528f0f2e109de72588efe33d6ca0af6 to your computer and use it in GitHub Desktop.
Download videos from dailywire.com using yt-dlp versions which don't support dailywire
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage: dailywire-dl [options] <url>
Download a Daily Wire episode by fetching signed playback data from the
middleware API, then downloading the Mux stream with yt-dlp.
Options:
-c, --cookies <file> Cookies file (JSON or Netscape cookies.txt)
-a, --access-token <token> Daily Wire accessToken (JWT)
-r, --resolution <pixels> Pass -S "res:<pixels>" to yt-dlp (e.g. 720, 1080)
One of --cookies or --access-token is required.
Requires: curl, jq, yt-dlp
Examples:
./dailywire-dl -c cookies.txt https://www.dailywire.com/episode/foo
./dailywire-dl --cookies cookies.json \
"https://www.dailywire.com/episode/foo?elementPosition=0"
./dailywire-dl -a "$ACCESS_TOKEN" -r 720 \
https://www.dailywire.com/episode/foo
EOF
}
extract_slug() {
local input_url="$1"
printf '%s' "$input_url" | sed -E 's/\?.*//; s#.*/episode/##; s#/.*##'
}
is_json_cookies_file() {
local file="$1"
jq -e 'type == "array"' "$file" >/dev/null 2>&1
}
extract_access_token_from_cookies_file() {
local file="$1"
if is_json_cookies_file "$file"; then
jq -r '.[] | select(.name == "accessToken") | .value' "$file"
else
awk -F'\t' '$6 == "accessToken" { print $7; exit }' "$file"
fi
}
middleware_origin="https://middleware-prod.dailywire.com"
fetch_episode_from_middleware() {
local slug="$1"
local access_token="$2"
curl -sS \
"${middleware_origin}/middleware/v4/getEpisodeWeb?slug=${slug}" \
-H "Authorization: Bearer ${access_token}" \
-H "Accept: application/json" \
-H "Origin: https://www.dailywire.com" \
-H "Referer: https://www.dailywire.com/episode/${slug}"
}
resolution=""
cookies_file=""
access_token=""
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
usage
exit 0
;;
-c|--cookies)
if [[ $# -lt 2 ]]; then
echo "error: $1 requires a value" >&2
exit 1
fi
cookies_file="$2"
shift 2
;;
-a|--access-token)
if [[ $# -lt 2 ]]; then
echo "error: $1 requires a value" >&2
exit 1
fi
access_token="$2"
shift 2
;;
-r|--resolution)
if [[ $# -lt 2 ]]; then
echo "error: $1 requires a value" >&2
exit 1
fi
resolution="$2"
shift 2
;;
--)
shift
break
;;
-*)
echo "error: unknown option: $1" >&2
usage >&2
exit 1
;;
*)
break
;;
esac
done
if [[ $# -ne 1 ]]; then
usage >&2
exit 1
fi
if [[ -n "$cookies_file" && -n "$access_token" ]]; then
echo "error: use either --cookies or --access-token, not both" >&2
exit 1
fi
if [[ -z "$cookies_file" && -z "$access_token" ]]; then
echo "error: either --cookies or --access-token is required" >&2
usage >&2
exit 1
fi
if [[ -n "$resolution" && ! "$resolution" =~ ^[0-9]+$ ]]; then
echo "error: resolution must be a positive integer (e.g. 720 or 1080)" >&2
exit 1
fi
require_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "error: $1 is required" >&2
exit 1
fi
}
require_cmd curl
require_cmd jq
require_cmd yt-dlp
url="$1"
slug="$(extract_slug "$url")"
if [[ -z "$slug" ]]; then
echo "error: could not extract episode slug from URL" >&2
exit 1
fi
if [[ -n "$cookies_file" ]]; then
if [[ ! -f "$cookies_file" ]]; then
echo "error: cookies file not found: $cookies_file" >&2
exit 1
fi
access_token="$(extract_access_token_from_cookies_file "$cookies_file")"
if [[ -z "$access_token" || "$access_token" == "null" ]]; then
echo "error: accessToken not found in $cookies_file" >&2
exit 1
fi
fi
echo "Fetching episode metadata for ${slug}..." >&2
episode_json="$(fetch_episode_from_middleware "$slug" "$access_token")"
if ! jq -e . >/dev/null 2>&1 <<<"$episode_json"; then
echo "error: middleware API returned invalid JSON" >&2
printf '%s\n' "$episode_json" >&2
exit 1
fi
if jq -e '.error | type == "string" and length > 0' >/dev/null 2>&1 <<<"$episode_json"; then
echo "error: middleware API request failed" >&2
jq . >&2 <<<"$episode_json"
exit 1
fi
title="$(jq -r '.title // empty' <<<"$episode_json")"
playback_id="$(jq -r '.muxPlaybackId // empty' <<<"$episode_json")"
playback_token="$(jq -r '.muxPlaybackToken // empty' <<<"$episode_json")"
if [[ -z "$title" || -z "$playback_id" || -z "$playback_token" ]]; then
echo "error: could not find episode title or signed Mux stream URL" >&2
echo "note: ensure the access token is current" >&2
exit 1
fi
content_url="https://stream.mux.com/${playback_id}.m3u8?token=${playback_token}"
# Keep the page title; only strip chars illegal on Linux/macOS (/ and control chars).
cleaned_title="$(printf '%s' "$title" | tr -d '\0/' | sed $'s/[\001-\037\177]//g')"
if [[ -z "$cleaned_title" ]]; then
cleaned_title="dailywire-episode"
fi
output_title="$cleaned_title"
if [[ -n "$resolution" ]]; then
output_title="${cleaned_title} ${resolution}p"
fi
echo "Title: $title" >&2
if [[ -n "$resolution" ]]; then
echo "Resolution: ${resolution}p" >&2
fi
echo "Downloading..." >&2
ytdlp_args=(
--ignore-config
--no-warnings
--merge-output-format mp4
--no-mtime
)
if [[ -n "$resolution" ]]; then
ytdlp_args+=(-S "res:${resolution}")
fi
yt-dlp \
"${ytdlp_args[@]}" \
"$content_url" \
-o "${output_title}.%(ext)s"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment