[Bug]: User agent error while downloading podcast episodes #3044

Open
opened 2026-04-25 00:13:14 +02:00 by adam · 2 comments
Owner

Originally created by @Gloopzlemeep on GitHub (Oct 20, 2025).

What happened?

For the last couple of weeks, new episodes for Lemonade Stand Podcast have failed to download.

Getting error related to User-Agent.

What did you expect to happen?

Episode downloads

Steps to reproduce the issue

  1. Search Lemonade Stand Podcast
  2. Attempt to download any episode

Audiobookshelf version

v2.30.0

How are you running audiobookshelf?

Docker

What OS is your Audiobookshelf server hosted from?

Linux

If the issue is being seen in the UI, what browsers are you seeing the problem on?

None

Logs

2025-10-20 15:11:55.426

DEBUG

[podcastUtils] getPodcastFeed for "https://feeds.megaphone.fm/VMP5629614579"

2025-10-20 15:11:55.697

DEBUG

[podcastUtils] getPodcastFeed for "https://feeds.megaphone.fm/VMP5629614579" success - parsing xml

2025-10-20 15:12:00.125

DEBUG

[fileUtils] Sanitized filename "Will The Peace Last? | Lemonade Stand 🍋.mp3" to "Will The Peace Last Lemonade Stand 🍋.mp3" (82 bytes)

2025-10-20 15:12:00.128

DEBUG

[Watcher] addIgnoreDir: Ignoring directory "/podcasts/Lemonade Stand"

2025-10-20 15:12:03.625

WARN

[ffmpegHelpers] Failed to download podcast episode with User-Agent "audiobookshelf (+https://audiobookshelf.org; like iTMS)" for url "https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3"

2025-10-20 15:12:06.100

WARN

[ffmpegHelpers] Failed to download podcast episode with User-Agent "audiobookshelf (+https://audiobookshelf.org)" for url "https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3"

2025-10-20 15:12:06.104

ERROR

[ffmpegHelpers] All User-Agent attempts failed for url "https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3" AggregateError [ETIMEDOUT]: at internalConnectMultiple (node:net:1122:18) at internalConnectMultiple (node:net:1190:5) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { code: 'ETIMEDOUT', errors: [ Error: connect ETIMEDOUT 52.2.20.172:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '52.2.20.172', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4711:d9b5:1815:6cd4:84ae:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4711:d9b5:1815:6cd4:84ae', port: 443 }, Error: connect ETIMEDOUT 3.213.238.40:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '3.213.238.40', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4712:99e9:4798:7274:3210:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4712:99e9:4798:7274:3210', port: 443 }, Error: connect ETIMEDOUT 3.89.0.232:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '3.89.0.232', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4712:3211:4776:7bfc:861:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4712:3211:4776:7bfc:861', port: 443 }, Error: connect ETIMEDOUT 34.228.126.24:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '34.228.126.24', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4711:b7de:bb7d:9633:242f:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4711:b7de:bb7d:9633:242f', port: 443 } ], config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [Function: httpAdapter], transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 30000, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: { FormData: [Function] }, validateStatus: [Function: validateStatus], headers: { Accept: '*/*', 'User-Agent': 'audiobookshelf (+https://audiobookshelf.org)' }, url: 'https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', method: 'get', responseType: 'stream', data: undefined }, request: <ref *1> Writable { _events: { close: undefined, error: [Function: handleRequestError], prefinish: undefined, finish: undefined, drain: undefined, response: [Function: handleResponse], socket: [Array], timeout: undefined, abort: undefined }, _writableState: WritableState { highWaterMark: 16384, length: 0, corked: 0, onwrite: [Function: bound onwrite], writelen: 0, bufferedIndex: 0, pendingcb: 0, [Symbol(kState)]: 17580812, [Symbol(kBufferedValue)]: null }, _maxListeners: undefined, _options: { maxRedirects: 21, maxBodyLength: 10485760, protocol: 'https:', path: '/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', method: 'GET', headers: [Object], agent: undefined, agents: [Object], auth: null, hostname: 'pscrb.fm', port: 0, nativeProtocols: [Object], pathname: '/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', host: 'pscrb.fm', href: 'https://pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', query: null, search: null, hash: null }, _ended: true, _ending: true, _redirectCount: 3, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _eventsCount: 3, _onNativeResponse: [Function (anonymous)], _currentRequest: ClientRequest { _events: [Object: null prototype], _eventsCount: 7, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: true, chunkedEncoding: false, shouldKeepAlive: true, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: false, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, strictContentLength: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, _closed: false, socket: [TLSSocket], _header: 'GET /rss/p/traffic.megaphone.fm/VMP4903015175.mp3 HTTP/1.1\r\n' + 'Accept: */*\r\n' + 'User-Agent: audiobookshelf (+https://audiobookshelf.org)\r\n' + 'Host: pscrb.fm\r\n' + 'Connection: keep-alive\r\n' + '\r\n', _keepAliveTimeout: 0, _onPendingData: [Function: nop], agent: [Agent], socketPath: undefined, method: 'GET', maxHeaderSize: undefined, insecureHTTPParser: undefined, joinDuplicateHeaders: undefined, path: '/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', _ended: false, res: null, aborted: false, timeoutCb: [Function: emitRequestTimeout], upgradeOrConnect: false, parser: null, maxHeadersCount: null, reusedSocket: false, host: 'pscrb.fm', protocol: 'https:', _redirectable: [Circular *1], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(kBytesWritten)]: 0, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype], [Symbol(errored)]: null, [Symbol(kHighWaterMark)]: 16384, [Symbol(kRejectNonStandardBodyWrites)]: false, [Symbol(kUniqueHeaders)]: null }, _currentUrl: 'https://pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', _timeout: null, _isRedirect: true, [Symbol(shapeMode)]: true, [Symbol(kCapture)]: false } }

Additional Notes

No response

Originally created by @Gloopzlemeep on GitHub (Oct 20, 2025). ### What happened? For the last couple of weeks, new episodes for Lemonade Stand Podcast have failed to download. Getting error related to User-Agent. ### What did you expect to happen? Episode downloads ### Steps to reproduce the issue 1. Search Lemonade Stand Podcast 2. Attempt to download any episode ### Audiobookshelf version v2.30.0 ### How are you running audiobookshelf? Docker ### What OS is your Audiobookshelf server hosted from? Linux ### If the issue is being seen in the UI, what browsers are you seeing the problem on? None ### Logs ```shell 2025-10-20 15:11:55.426 DEBUG [podcastUtils] getPodcastFeed for "https://feeds.megaphone.fm/VMP5629614579" 2025-10-20 15:11:55.697 DEBUG [podcastUtils] getPodcastFeed for "https://feeds.megaphone.fm/VMP5629614579" success - parsing xml 2025-10-20 15:12:00.125 DEBUG [fileUtils] Sanitized filename "Will The Peace Last? | Lemonade Stand 🍋.mp3" to "Will The Peace Last Lemonade Stand 🍋.mp3" (82 bytes) 2025-10-20 15:12:00.128 DEBUG [Watcher] addIgnoreDir: Ignoring directory "/podcasts/Lemonade Stand" 2025-10-20 15:12:03.625 WARN [ffmpegHelpers] Failed to download podcast episode with User-Agent "audiobookshelf (+https://audiobookshelf.org; like iTMS)" for url "https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3" 2025-10-20 15:12:06.100 WARN [ffmpegHelpers] Failed to download podcast episode with User-Agent "audiobookshelf (+https://audiobookshelf.org)" for url "https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3" 2025-10-20 15:12:06.104 ERROR [ffmpegHelpers] All User-Agent attempts failed for url "https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3" AggregateError [ETIMEDOUT]: at internalConnectMultiple (node:net:1122:18) at internalConnectMultiple (node:net:1190:5) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { code: 'ETIMEDOUT', errors: [ Error: connect ETIMEDOUT 52.2.20.172:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '52.2.20.172', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4711:d9b5:1815:6cd4:84ae:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4711:d9b5:1815:6cd4:84ae', port: 443 }, Error: connect ETIMEDOUT 3.213.238.40:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '3.213.238.40', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4712:99e9:4798:7274:3210:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4712:99e9:4798:7274:3210', port: 443 }, Error: connect ETIMEDOUT 3.89.0.232:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '3.89.0.232', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4712:3211:4776:7bfc:861:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4712:3211:4776:7bfc:861', port: 443 }, Error: connect ETIMEDOUT 34.228.126.24:443 at createConnectionError (node:net:1652:14) at Timeout.internalConnectMultipleTimeout (node:net:1711:38) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -110, code: 'ETIMEDOUT', syscall: 'connect', address: '34.228.126.24', port: 443 }, Error: connect ENETUNREACH 2600:1f10:4c2d:4711:b7de:bb7d:9633:242f:443 - Local (:::0) at internalConnectMultiple (node:net:1186:16) at Timeout.internalConnectMultipleTimeout (node:net:1716:5) at listOnTimeout (node:internal/timers:583:11) at process.processTimers (node:internal/timers:519:7) { errno: -101, code: 'ENETUNREACH', syscall: 'connect', address: '2600:1f10:4c2d:4711:b7de:bb7d:9633:242f', port: 443 } ], config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [Function: httpAdapter], transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 30000, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: { FormData: [Function] }, validateStatus: [Function: validateStatus], headers: { Accept: '*/*', 'User-Agent': 'audiobookshelf (+https://audiobookshelf.org)' }, url: 'https://www.podtrac.com/pts/redirect.mp3/pdst.fm/e/chrt.fm/track/524GE/pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', method: 'get', responseType: 'stream', data: undefined }, request: <ref *1> Writable { _events: { close: undefined, error: [Function: handleRequestError], prefinish: undefined, finish: undefined, drain: undefined, response: [Function: handleResponse], socket: [Array], timeout: undefined, abort: undefined }, _writableState: WritableState { highWaterMark: 16384, length: 0, corked: 0, onwrite: [Function: bound onwrite], writelen: 0, bufferedIndex: 0, pendingcb: 0, [Symbol(kState)]: 17580812, [Symbol(kBufferedValue)]: null }, _maxListeners: undefined, _options: { maxRedirects: 21, maxBodyLength: 10485760, protocol: 'https:', path: '/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', method: 'GET', headers: [Object], agent: undefined, agents: [Object], auth: null, hostname: 'pscrb.fm', port: 0, nativeProtocols: [Object], pathname: '/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', host: 'pscrb.fm', href: 'https://pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', query: null, search: null, hash: null }, _ended: true, _ending: true, _redirectCount: 3, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _eventsCount: 3, _onNativeResponse: [Function (anonymous)], _currentRequest: ClientRequest { _events: [Object: null prototype], _eventsCount: 7, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: true, chunkedEncoding: false, shouldKeepAlive: true, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: false, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, strictContentLength: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, _closed: false, socket: [TLSSocket], _header: 'GET /rss/p/traffic.megaphone.fm/VMP4903015175.mp3 HTTP/1.1\r\n' + 'Accept: */*\r\n' + 'User-Agent: audiobookshelf (+https://audiobookshelf.org)\r\n' + 'Host: pscrb.fm\r\n' + 'Connection: keep-alive\r\n' + '\r\n', _keepAliveTimeout: 0, _onPendingData: [Function: nop], agent: [Agent], socketPath: undefined, method: 'GET', maxHeaderSize: undefined, insecureHTTPParser: undefined, joinDuplicateHeaders: undefined, path: '/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', _ended: false, res: null, aborted: false, timeoutCb: [Function: emitRequestTimeout], upgradeOrConnect: false, parser: null, maxHeadersCount: null, reusedSocket: false, host: 'pscrb.fm', protocol: 'https:', _redirectable: [Circular *1], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(kBytesWritten)]: 0, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype], [Symbol(errored)]: null, [Symbol(kHighWaterMark)]: 16384, [Symbol(kRejectNonStandardBodyWrites)]: false, [Symbol(kUniqueHeaders)]: null }, _currentUrl: 'https://pscrb.fm/rss/p/traffic.megaphone.fm/VMP4903015175.mp3', _timeout: null, _isRedirect: true, [Symbol(shapeMode)]: true, [Symbol(kCapture)]: false } } ``` ### Additional Notes _No response_
adam added the bug label 2026-04-25 00:13:14 +02:00
Author
Owner

@Gloopzlemeep commented on GitHub (Oct 21, 2025):

I assume the issue is just on the podcast pprovider end not accepting the ABS user agent but is there anything that can be done on the ABS end to mitigate? Like the ability to manually change the User Agent used when downloading a particular podcast?

@Gloopzlemeep commented on GitHub (Oct 21, 2025): I assume the issue is just on the podcast pprovider end not accepting the ABS user agent but is there anything that can be done on the ABS end to mitigate? Like the ability to manually change the User Agent used when downloading a particular podcast?
Author
Owner

@AlexanderMcColl commented on GitHub (Nov 2, 2025):

I get the same error from a megaphone.fm feed.
For me, the podcast is Triggernometry, rss feed is: https://feeds.megaphone.fm/AALT9618167458

[ffmpegHelpers] Failed to download podcast episode with User-Agent "audiobookshelf (+https://audiobookshelf.org; like iTMS)" for url "https://pdst.fm/e/prfx.byspotify.com/e/pscrb.fm/rss/p/s.gum.fm/s-65a84022ad283b3c6fda9305/mgln.ai/e/p63400/mgln.ai/e/137/traffic.megaphone.fm/AALT8622187185.mp3?updated=1753933126"

Going to this address in a browser, after some redirects, I end up at https://dcs-spotify.megaphone.fm/AALT8622187185.mp3?key=9bcad9c14a756923a992bcb60f90f6c6&request_event_id=131443a8-7097-47f2-9dd1-affe5ec3b15a&session_id=131443a8-7097-47f2-9dd1-affe5ec3b15a&timetoken=1762115802_612DB2373CA5822C03F7F693253FA5F6

Here, I'm served the mp3 file just fine, so if we could customise the user-agent we're sending, that ought to do it?

@AlexanderMcColl commented on GitHub (Nov 2, 2025): I get the same error from a megaphone.fm feed. For me, the podcast is Triggernometry, rss feed is: https://feeds.megaphone.fm/AALT9618167458 [ffmpegHelpers] Failed to download podcast episode with User-Agent "audiobookshelf (+https://audiobookshelf.org; like iTMS)" for url "https://pdst.fm/e/prfx.byspotify.com/e/pscrb.fm/rss/p/s.gum.fm/s-65a84022ad283b3c6fda9305/mgln.ai/e/p63400/mgln.ai/e/137/traffic.megaphone.fm/AALT8622187185.mp3?updated=1753933126" Going to this address in a browser, after some redirects, I end up at https://dcs-spotify.megaphone.fm/AALT8622187185.mp3?key=9bcad9c14a756923a992bcb60f90f6c6&request_event_id=131443a8-7097-47f2-9dd1-affe5ec3b15a&session_id=131443a8-7097-47f2-9dd1-affe5ec3b15a&timetoken=1762115802_612DB2373CA5822C03F7F693253FA5F6 Here, I'm served the mp3 file just fine, so if we could customise the user-agent we're sending, that ought to do it?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/audiobookshelf#3044