[GH-ISSUE #174] SSL certificate verify failed #29

Closed
opened 2026-10-13 19:46:04 +00:00 by bsakaguchi · 4 comments
Owner

Originally created by @print423 on GitHub (Aug 29, 2026).
Original GitHub issue: https://github.com/Glitchy-Sheep/boosty-downloader/issues/174

🐛 What happened?

When I try to run the script, I get an SSL certificate verification error. I updated the certifi, but nothing has changed. Is this a problem on my end or on their server?

📋 Error output

[20:07:13] Boosty_Downloader.ERROR ❌: Network error while talking to Boosty:                    
           ClientConnectorCertificateError: Cannot connect to host api.boosty.to:443 ssl:True    
           [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify   
           failed: certificate has expired (_ssl.c:1082)')]                                      
           Boosty_Downloader.INFO 🔹: Re-run with --debug and attach boosty-downloader-debug.log 
           to a GitHub issue.                                                                    

🖥️ Environment

  • boosty-downloader version: 3.7.0
  • OS: Win10
  • Python 3.14.7

debug-file:

boosty-downloader 3.7.0 | Windows-10-10.0.19043-SP0 | Python 3.14.7
argv: O:\Python314\Scripts\boosty-downloader.EXE --debug download --username badcomedian
[20:06:06] INFO     Boosty_Downloader.INFO 🔹: You are using the latest boosty-downloader version.                      
                                                                                                                        
           INFO     Destination directory: O:\Python314\Scripts\boosty-downloads\badcomedian                            
           INFO     ----------------------------------------------------------------------------------                  
                    Script will download: boosty_videos, external_videos, post_content, files, audio                    
                    ----------------------------------------------------------------------------------                  
                                                                                                                        
           DEBUG    #1 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 1/5)                      
           DEBUG    #1 connecting...                                                                                    
           DEBUG    #1 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.25s (dns 0.079s, conn   
                    0.252s)                                                                                             
[20:06:07] DEBUG    #2 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 2/5)                      
           DEBUG    #2 connecting...                                                                                    
           DEBUG    #2 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn    
                    0.163s)                                                                                             
           DEBUG    #3 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 3/5)                      
           DEBUG    #3 connecting...                                                                                    
           DEBUG    #3 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn    
                    0.159s)                                                                                             
[20:06:08] DEBUG    #4 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 4/5)                      
           DEBUG    #4 connecting...                                                                                    
           DEBUG    #4 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn    
                    0.162s)                                                                                             
[20:06:10] DEBUG    #5 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 5/5)                      
           DEBUG    #5 connecting...                                                                                    
           DEBUG    #5 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn    
                    0.166s)                                                                                             
           ERROR    Boosty_Downloader.ERROR ❌: Network error while talking to Boosty: ClientConnectorCertificateError: 
                    Cannot connect to host api.boosty.to:443 ssl:True [SSLCertVerificationError: (1, '[SSL:             
                    CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1082)')]      
           DEBUG    Full traceback of the error:                                                                        
                    ┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐
                    │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1316 in _wrap_create_connection              │
                    │                                                                                                  │
                    │   1313 │   │   │   │   │   and sys.version_info >= (3, 11)                                       │
                    │   1314 │   │   │   │   ):                                                                        │
                    │   1315 │   │   │   │   │   kwargs["ssl_shutdown_timeout"] = self._ssl_shutdown_timeout           │
                    │ > 1316 │   │   │   │   return await self._loop.create_connection(*args, **kwargs, sock=sock)     │
                    │   1317 │   │   except cert_errors as exc:                                                        │
                    │   1318 │   │   │   raise ClientConnectorCertificateError(req.connection_key, exc) from exc       │
                    │   1319 │   │   except ssl_errors as exc:                                                         │
                    │                                                                                                  │
                    │ O:\Python314\Lib\asyncio\base_events.py:1199 in create_connection                                │
                    │                                                                                                  │
                    │   1196 │   │   │   │   raise ValueError(                                                         │
                    │   1197 │   │   │   │   │   f'A Stream Socket was expected, got {sock!r}')                        │
                    │   1198 │   │                                                                                     │
                    │ > 1199 │   │   transport, protocol = await self._create_connection_transport(                    │
                    │   1200 │   │   │   sock, protocol_factory, ssl, server_hostname,                                 │
                    │   1201 │   │   │   ssl_handshake_timeout=ssl_handshake_timeout,                                  │
                    │   1202 │   │   │   ssl_shutdown_timeout=ssl_shutdown_timeout)                                    │
                    │                                                                                                  │
                    │ O:\Python314\Lib\asyncio\base_events.py:1232 in _create_connection_transport                     │
                    │                                                                                                  │
                    │   1229 │   │   │   transport = self._make_socket_transport(sock, protocol, waiter)               │
                    │   1230 │   │                                                                                     │
                    │   1231 │   │   try:                                                                              │
                    │ > 1232 │   │   │   await waiter                                                                  │
                    │   1233 │   │   except:                                                                           │
                    │   1234 │   │   │   transport.close()                                                             │
                    │   1235 │   │   │   raise                                                                         │
                    │                                                                                                  │
                    │ O:\Python314\Lib\asyncio\sslproto.py:581 in _on_handshake_complete                               │
                    │                                                                                                  │
                    │   578 │   │   │   if handshake_exc is None:                                                      │
                    │   579 │   │   │   │   self._set_state(SSLProtocolState.WRAPPED)                                  │
                    │   580 │   │   │   else:                                                                          │
                    │ > 581 │   │   │   │   raise handshake_exc                                                        │
                    │   582 │   │   │                                                                                  │
                    │   583 │   │   │   peercert = sslobj.getpeercert()                                                │
                    │   584 │   │   except Exception as exc:                                                           │
                    │                                                                                                  │
                    │ O:\Python314\Lib\asyncio\sslproto.py:563 in _do_handshake                                        │
                    │                                                                                                  │
                    │   560 │                                                                                          │
                    │   561 │   def _do_handshake(self):                                                               │
                    │   562 │   │   try:                                                                               │
                    │ > 563 │   │   │   self._sslobj.do_handshake()                                                    │
                    │   564 │   │   except SSLAgainErrors:                                                             │
                    │   565 │   │   │   self._process_outgoing()                                                       │
                    │   566 │   │   except ssl.SSLError as exc:                                                        │
                    │                                                                                                  │
                    │ O:\Python314\Lib\ssl.py:951 in do_handshake                                                      │
                    │                                                                                                  │
                    │    948 │                                                                                         │
                    │    949 │   def do_handshake(self):                                                               │
                    │    950 │   │   """Start the SSL/TLS handshake."""                                                │
                    │ >  951 │   │   self._sslobj.do_handshake()                                                       │
                    │    952 │                                                                                         │
                    │    953 │   def unwrap(self):                                                                     │
                    │    954 │   │   """Start the SSL shutdown handshake."""                                           │
                    └──────────────────────────────────────────────────────────────────────────────────────────────────┘
                    SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate   
                    has expired (_ssl.c:1082)                                                                           
                                                                                                                        
                    The above exception was the direct cause of the following exception:                                
                                                                                                                        
                    ┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐
                    │ O:\Python314\Lib\site-packages\boosty_downloader\cli\commands\download.py:183 in                 │
                    │ download_entrypoint                                                                              │
                    │                                                                                                  │
                    │   180 │   │   │   - Cache doesn't check local files, you can delete them and they still won't    │
                    │       re-download.                                                                               │
                    │   181 │   │                                                                                      │
                    │   182 │   │   """                                                                                │
                    │ > 183 │   │   asyncio.run(                                                                       │
                    │   184 │   │   │   _download_handler(                                                             │
                    │   185 │   │   │   │   username=username,                                                         │
                    │   186 │   │   │   │   post_url=post_url,                                                         │
                    │                                                                                                  │
                    │ O:\Python314\Lib\asyncio\runners.py:205 in run                                                   │
                    │                                                                                                  │
                    │   202 │   │   │   "asyncio.run() cannot be called from a running event loop")                    │
                    │   203 │                                                                                          │
                    │   204 │   with Runner(debug=debug, loop_factory=loop_factory) as runner:                         │
                    │ > 205 │   │   return runner.run(main)                                                            │
                    │   206                                                                                            │
                    │   207                                                                                            │
                    │   208 def _cancel_all_tasks(loop):                                                               │
                    │                                                                                                  │
                    │ O:\Python314\Lib\asyncio\runners.py:128 in run                                                   │
                    │                                                                                                  │
                    │   125 │   │                                                                                      │
                    │   126 │   │   self._interrupt_count = 0                                                          │
                    │   127 │   │   try:                                                                               │
                    │ > 128 │   │   │   return self._loop.run_until_complete(task)                                     │
                    │   129 │   │   except exceptions.CancelledError:                                                  │
                    │   130 │   │   │   if self._interrupt_count > 0:                                                  │
                    │   131 │   │   │   │   uncancel = getattr(task, "uncancel", None)                                 │
                    │                                                                                                  │
                    │ O:\Python314\Lib\asyncio\base_events.py:720 in run_until_complete                                │
                    │                                                                                                  │
                    │    717 │   │   if not future.done():                                                             │
                    │    718 │   │   │   raise RuntimeError('Event loop stopped before Future completed.')             │
                    │    719 │   │                                                                                     │
                    │ >  720 │   │   return future.result()                                                            │
                    │    721 │                                                                                         │
                    │    722 │   def stop(self):                                                                       │
                    │    723 │   │   """Stop running the event loop.                                                   │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\boosty_downloader\cli\commands\download.py:123 in                 │
                    │ _download_handler                                                                                │
                    │                                                                                                  │
                    │   120 │   │   │   content_type_filter=content_type_filter,                                       │
                    │   121 │   │   )                                                                                  │
                    │   122 │   │                                                                                      │
                    │ > 123 │   │   await DownloadAllPostUseCase(                                                      │
                    │   124 │   │   │   author_name=username,                                                          │
                    │   125 │   │   │   boosty_api=app_env.boosty_api_client,                                          │
                    │   126 │   │   │   destination=app_env.destination_directory,                                     │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\boosty_downloader\application\use_cases\download_all_posts.py:100 │
                    │ in execute                                                                                       │
                    │                                                                                                  │
                    │    97 │   │   │   threshold=None if self.skip_all_failures else CONSECUTIVE_FAILURES_LIMIT       │
                    │    98 │   │   )                                                                                  │
                    │    99 │   │                                                                                      │
                    │ > 100 │   │   async for page in posts_iterator:                                                  │
                    │   101 │   │   │   count = len(page.posts)                                                        │
                    │   102 │   │   │   current_page += 1                                                              │
                    │   103                                                                                            │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\boosty_downloader\infrastructure\boosty_api\core\client.py:277 in │
                    │ iterate_over_posts                                                                               │
                    │                                                                                                  │
                    │   274 │   │   """                                                                                │
                    │   275 │   │   offset = None                                                                      │
                    │   276 │   │   while True:                                                                        │
                    │ > 277 │   │   │   response = await self.get_author_posts(                                        │
                    │   278 │   │   │   │   author_name,                                                               │
                    │   279 │   │   │   │   offset=offset,                                                             │
                    │   280 │   │   │   │   limit=posts_per_page,                                                      │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\boosty_downloader\infrastructure\boosty_api\core\client.py:160 in │
                    │ get_author_posts                                                                                 │
                    │                                                                                                  │
                    │   157 │   │   """                                                                                │
                    │   158 │   │   endpoint = f'blog/{author_name}/post/'                                             │
                    │   159 │   │                                                                                      │
                    │ > 160 │   │   posts_raw = await self._throttled_get(                                             │
                    │   161 │   │   │   endpoint,                                                                      │
                    │   162 │   │   │   params=filter_none_params(                                                     │
                    │   163 │   │   │   │   {                                                                          │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\boosty_downloader\infrastructure\boosty_api\core\client.py:142 in │
                    │ _throttled_get                                                                                   │
                    │                                                                                                  │
                    │   139 │   │                                                                                      │
                    │   140 │   │   if self._limiter:                                                                  │
                    │   141 │   │   │   async with self._limiter:                                                      │
                    │ > 142 │   │   │   │   return await self.session.get(url, params=params, headers=headers)         │
                    │   143 │   │   return await self.session.get(url, params=params, headers=headers)                 │
                    │   144 │                                                                                          │
                    │   145 │   async def get_author_posts(                                                            │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp_retry\client.py:158 in __aenter__                         │
                    │                                                                                                  │
                    │   155 │   │   return self.__aenter__().__await__()                                               │
                    │   156 │                                                                                          │
                    │   157 │   async def __aenter__(self) -> ClientResponse:                                          │
                    │ > 158 │   │   return await self._do_request()                                                    │
                    │   159 │                                                                                          │
                    │   160 │   async def __aexit__(                                                                   │
                    │   161 │   │   self,                                                                              │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp_retry\client.py:119 in _do_request                        │
                    │                                                                                                  │
                    │   116 │   │   │   │   except IndexError:                                                         │
                    │   117 │   │   │   │   │   params = self._params_list[-1]                                         │
                    │   118 │   │   │   │                                                                              │
                    │ > 119 │   │   │   │   response: ClientResponse = await self._request_func(                       │
                    │   120 │   │   │   │   │   params.method,                                                         │
                    │   121 │   │   │   │   │   params.url,                                                            │
                    │   122 │   │   │   │   │   headers=params.headers,                                                │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp\client.py:858 in _request                                 │
                    │                                                                                                  │
                    │    855 │   │   │   │   │   │   handler = _connect_and_send_request                               │
                    │    856 │   │   │   │   │                                                                         │
                    │    857 │   │   │   │   │   try:                                                                  │
                    │ >  858 │   │   │   │   │   │   resp = await handler(req)                                         │
                    │    859 │   │   │   │   │   # Client connector errors should not be retried                       │
                    │    860 │   │   │   │   │   except (                                                              │
                    │    861 │   │   │   │   │   │   ConnectionTimeoutError,                                           │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp\client.py:812 in _connect_and_send_request                │
                    │                                                                                                  │
                    │    809 │   │   │   │   │   │   # connection timeout                                              │
                    │    810 │   │   │   │   │   │   assert self._connector is not None                                │
                    │    811 │   │   │   │   │   │   try:                                                              │
                    │ >  812 │   │   │   │   │   │   │   conn = await self._connector.connect(                         │
                    │    813 │   │   │   │   │   │   │   │   req, traces=traces, timeout=real_timeout                  │
                    │    814 │   │   │   │   │   │   │   )                                                             │
                    │    815 │   │   │   │   │   │   except asyncio.TimeoutError as exc:                               │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp\connector.py:657 in connect                               │
                    │                                                                                                  │
                    │    654 │   │   │   │   if traces:                                                                │
                    │    655 │   │   │   │   │   for trace in traces:                                                  │
                    │    656 │   │   │   │   │   │   await trace.send_connection_create_start()                        │
                    │ >  657 │   │   │   │   proto = await self._create_connection(req, traces, timeout)               │
                    │    658 │   │   │   │   if traces:                                                                │
                    │    659 │   │   │   │   │   for trace in traces:                                                  │
                    │    660 │   │   │   │   │   │   await trace.send_connection_create_end()                          │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1242 in _create_connection                   │
                    │                                                                                                  │
                    │   1239 │   │   if req.proxy:                                                                     │
                    │   1240 │   │   │   _, proto = await self._create_proxy_connection(req, traces, timeout)          │
                    │   1241 │   │   else:                                                                             │
                    │ > 1242 │   │   │   _, proto = await self._create_direct_connection(req, traces, timeout)         │
                    │   1243 │   │                                                                                     │
                    │   1244 │   │   return proto                                                                      │
                    │   1245                                                                                           │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1620 in _create_direct_connection            │
                    │                                                                                                  │
                    │   1617 │   │   │   return transp, proto                                                          │
                    │   1618 │   │   else:                                                                             │
                    │   1619 │   │   │   assert last_exc is not None                                                   │
                    │ > 1620 │   │   │   raise last_exc                                                                │
                    │   1621 │                                                                                         │
                    │   1622 │   async def _create_proxy_connection(                                                   │
                    │   1623 │   │   self, req: ClientRequest, traces: list["Trace"], timeout: "ClientTimeout"         │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1589 in _create_direct_connection            │
                    │                                                                                                  │
                    │   1586 │   │   │   )                                                                             │
                    │   1587 │   │   │                                                                                 │
                    │   1588 │   │   │   try:                                                                          │
                    │ > 1589 │   │   │   │   transp, proto = await self._wrap_create_connection(                       │
                    │   1590 │   │   │   │   │   self._factory,                                                        │
                    │   1591 │   │   │   │   │   timeout=timeout,                                                      │
                    │   1592 │   │   │   │   │   ssl=sslcontext,                                                       │
                    │                                                                                                  │
                    │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1318 in _wrap_create_connection              │
                    │                                                                                                  │
                    │   1315 │   │   │   │   │   kwargs["ssl_shutdown_timeout"] = self._ssl_shutdown_timeout           │
                    │   1316 │   │   │   │   return await self._loop.create_connection(*args, **kwargs, sock=sock)     │
                    │   1317 │   │   except cert_errors as exc:                                                        │
                    │ > 1318 │   │   │   raise ClientConnectorCertificateError(req.connection_key, exc) from exc       │
                    │   1319 │   │   except ssl_errors as exc:                                                         │
                    │   1320 │   │   │   raise ClientConnectorSSLError(req.connection_key, exc) from exc               │
                    │   1321 │   │   except OSError as exc:                                                            │
                    └──────────────────────────────────────────────────────────────────────────────────────────────────┘
                    ClientConnectorCertificateError: Cannot connect to host api.boosty.to:443 ssl:True                  
                    [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed:         
                    certificate has expired (_ssl.c:1082)')]                                                            
[20:06:11] INFO     Boosty_Downloader.INFO 🔹: Details written to boosty-downloader-debug.log - attach it to the issue. 

Originally created by @print423 on GitHub (Aug 29, 2026). Original GitHub issue: https://github.com/Glitchy-Sheep/boosty-downloader/issues/174 ## 🐛 What happened? When I try to run the script, I get an SSL certificate verification error. I updated the certifi, but nothing has changed. Is this a problem on my end or on their server? ## 📋 Error output ```text [20:07:13] Boosty_Downloader.ERROR ❌: Network error while talking to Boosty: ClientConnectorCertificateError: Cannot connect to host api.boosty.to:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1082)')] Boosty_Downloader.INFO 🔹: Re-run with --debug and attach boosty-downloader-debug.log to a GitHub issue. ``` ## 🖥️ Environment - boosty-downloader version: 3.7.0 - OS: Win10 - Python 3.14.7 debug-file: ```text boosty-downloader 3.7.0 | Windows-10-10.0.19043-SP0 | Python 3.14.7 argv: O:\Python314\Scripts\boosty-downloader.EXE --debug download --username badcomedian [20:06:06] INFO Boosty_Downloader.INFO 🔹: You are using the latest boosty-downloader version. INFO Destination directory: O:\Python314\Scripts\boosty-downloads\badcomedian INFO ---------------------------------------------------------------------------------- Script will download: boosty_videos, external_videos, post_content, files, audio ---------------------------------------------------------------------------------- DEBUG #1 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 1/5) DEBUG #1 connecting... DEBUG #1 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.25s (dns 0.079s, conn 0.252s) [20:06:07] DEBUG #2 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 2/5) DEBUG #2 connecting... DEBUG #2 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn 0.163s) DEBUG #3 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 3/5) DEBUG #3 connecting... DEBUG #3 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn 0.159s) [20:06:08] DEBUG #4 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 4/5) DEBUG #4 connecting... DEBUG #4 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn 0.162s) [20:06:10] DEBUG #5 GET https://api.boosty.to/v1/blog/badcomedian/post/?limit=... (attempt 5/5) DEBUG #5 connecting... DEBUG #5 -> FAIL ClientConnectorCertificateError <- SSLCertVerificationError in 0.17s (dns cache, conn 0.166s) ERROR Boosty_Downloader.ERROR ❌: Network error while talking to Boosty: ClientConnectorCertificateError: Cannot connect to host api.boosty.to:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1082)')] DEBUG Full traceback of the error: ┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐ │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1316 in _wrap_create_connection │ │ │ │ 1313 │ │ │ │ │ and sys.version_info >= (3, 11) │ │ 1314 │ │ │ │ ): │ │ 1315 │ │ │ │ │ kwargs["ssl_shutdown_timeout"] = self._ssl_shutdown_timeout │ │ > 1316 │ │ │ │ return await self._loop.create_connection(*args, **kwargs, sock=sock) │ │ 1317 │ │ except cert_errors as exc: │ │ 1318 │ │ │ raise ClientConnectorCertificateError(req.connection_key, exc) from exc │ │ 1319 │ │ except ssl_errors as exc: │ │ │ │ O:\Python314\Lib\asyncio\base_events.py:1199 in create_connection │ │ │ │ 1196 │ │ │ │ raise ValueError( │ │ 1197 │ │ │ │ │ f'A Stream Socket was expected, got {sock!r}') │ │ 1198 │ │ │ │ > 1199 │ │ transport, protocol = await self._create_connection_transport( │ │ 1200 │ │ │ sock, protocol_factory, ssl, server_hostname, │ │ 1201 │ │ │ ssl_handshake_timeout=ssl_handshake_timeout, │ │ 1202 │ │ │ ssl_shutdown_timeout=ssl_shutdown_timeout) │ │ │ │ O:\Python314\Lib\asyncio\base_events.py:1232 in _create_connection_transport │ │ │ │ 1229 │ │ │ transport = self._make_socket_transport(sock, protocol, waiter) │ │ 1230 │ │ │ │ 1231 │ │ try: │ │ > 1232 │ │ │ await waiter │ │ 1233 │ │ except: │ │ 1234 │ │ │ transport.close() │ │ 1235 │ │ │ raise │ │ │ │ O:\Python314\Lib\asyncio\sslproto.py:581 in _on_handshake_complete │ │ │ │ 578 │ │ │ if handshake_exc is None: │ │ 579 │ │ │ │ self._set_state(SSLProtocolState.WRAPPED) │ │ 580 │ │ │ else: │ │ > 581 │ │ │ │ raise handshake_exc │ │ 582 │ │ │ │ │ 583 │ │ │ peercert = sslobj.getpeercert() │ │ 584 │ │ except Exception as exc: │ │ │ │ O:\Python314\Lib\asyncio\sslproto.py:563 in _do_handshake │ │ │ │ 560 │ │ │ 561 │ def _do_handshake(self): │ │ 562 │ │ try: │ │ > 563 │ │ │ self._sslobj.do_handshake() │ │ 564 │ │ except SSLAgainErrors: │ │ 565 │ │ │ self._process_outgoing() │ │ 566 │ │ except ssl.SSLError as exc: │ │ │ │ O:\Python314\Lib\ssl.py:951 in do_handshake │ │ │ │ 948 │ │ │ 949 │ def do_handshake(self): │ │ 950 │ │ """Start the SSL/TLS handshake.""" │ │ > 951 │ │ self._sslobj.do_handshake() │ │ 952 │ │ │ 953 │ def unwrap(self): │ │ 954 │ │ """Start the SSL shutdown handshake.""" │ └──────────────────────────────────────────────────────────────────────────────────────────────────┘ SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1082) The above exception was the direct cause of the following exception: ┌─────────────────────────────── Traceback (most recent call last) ────────────────────────────────┐ │ O:\Python314\Lib\site-packages\boosty_downloader\cli\commands\download.py:183 in │ │ download_entrypoint │ │ │ │ 180 │ │ │ - Cache doesn't check local files, you can delete them and they still won't │ │ re-download. │ │ 181 │ │ │ │ 182 │ │ """ │ │ > 183 │ │ asyncio.run( │ │ 184 │ │ │ _download_handler( │ │ 185 │ │ │ │ username=username, │ │ 186 │ │ │ │ post_url=post_url, │ │ │ │ O:\Python314\Lib\asyncio\runners.py:205 in run │ │ │ │ 202 │ │ │ "asyncio.run() cannot be called from a running event loop") │ │ 203 │ │ │ 204 │ with Runner(debug=debug, loop_factory=loop_factory) as runner: │ │ > 205 │ │ return runner.run(main) │ │ 206 │ │ 207 │ │ 208 def _cancel_all_tasks(loop): │ │ │ │ O:\Python314\Lib\asyncio\runners.py:128 in run │ │ │ │ 125 │ │ │ │ 126 │ │ self._interrupt_count = 0 │ │ 127 │ │ try: │ │ > 128 │ │ │ return self._loop.run_until_complete(task) │ │ 129 │ │ except exceptions.CancelledError: │ │ 130 │ │ │ if self._interrupt_count > 0: │ │ 131 │ │ │ │ uncancel = getattr(task, "uncancel", None) │ │ │ │ O:\Python314\Lib\asyncio\base_events.py:720 in run_until_complete │ │ │ │ 717 │ │ if not future.done(): │ │ 718 │ │ │ raise RuntimeError('Event loop stopped before Future completed.') │ │ 719 │ │ │ │ > 720 │ │ return future.result() │ │ 721 │ │ │ 722 │ def stop(self): │ │ 723 │ │ """Stop running the event loop. │ │ │ │ O:\Python314\Lib\site-packages\boosty_downloader\cli\commands\download.py:123 in │ │ _download_handler │ │ │ │ 120 │ │ │ content_type_filter=content_type_filter, │ │ 121 │ │ ) │ │ 122 │ │ │ │ > 123 │ │ await DownloadAllPostUseCase( │ │ 124 │ │ │ author_name=username, │ │ 125 │ │ │ boosty_api=app_env.boosty_api_client, │ │ 126 │ │ │ destination=app_env.destination_directory, │ │ │ │ O:\Python314\Lib\site-packages\boosty_downloader\application\use_cases\download_all_posts.py:100 │ │ in execute │ │ │ │ 97 │ │ │ threshold=None if self.skip_all_failures else CONSECUTIVE_FAILURES_LIMIT │ │ 98 │ │ ) │ │ 99 │ │ │ │ > 100 │ │ async for page in posts_iterator: │ │ 101 │ │ │ count = len(page.posts) │ │ 102 │ │ │ current_page += 1 │ │ 103 │ │ │ │ O:\Python314\Lib\site-packages\boosty_downloader\infrastructure\boosty_api\core\client.py:277 in │ │ iterate_over_posts │ │ │ │ 274 │ │ """ │ │ 275 │ │ offset = None │ │ 276 │ │ while True: │ │ > 277 │ │ │ response = await self.get_author_posts( │ │ 278 │ │ │ │ author_name, │ │ 279 │ │ │ │ offset=offset, │ │ 280 │ │ │ │ limit=posts_per_page, │ │ │ │ O:\Python314\Lib\site-packages\boosty_downloader\infrastructure\boosty_api\core\client.py:160 in │ │ get_author_posts │ │ │ │ 157 │ │ """ │ │ 158 │ │ endpoint = f'blog/{author_name}/post/' │ │ 159 │ │ │ │ > 160 │ │ posts_raw = await self._throttled_get( │ │ 161 │ │ │ endpoint, │ │ 162 │ │ │ params=filter_none_params( │ │ 163 │ │ │ │ { │ │ │ │ O:\Python314\Lib\site-packages\boosty_downloader\infrastructure\boosty_api\core\client.py:142 in │ │ _throttled_get │ │ │ │ 139 │ │ │ │ 140 │ │ if self._limiter: │ │ 141 │ │ │ async with self._limiter: │ │ > 142 │ │ │ │ return await self.session.get(url, params=params, headers=headers) │ │ 143 │ │ return await self.session.get(url, params=params, headers=headers) │ │ 144 │ │ │ 145 │ async def get_author_posts( │ │ │ │ O:\Python314\Lib\site-packages\aiohttp_retry\client.py:158 in __aenter__ │ │ │ │ 155 │ │ return self.__aenter__().__await__() │ │ 156 │ │ │ 157 │ async def __aenter__(self) -> ClientResponse: │ │ > 158 │ │ return await self._do_request() │ │ 159 │ │ │ 160 │ async def __aexit__( │ │ 161 │ │ self, │ │ │ │ O:\Python314\Lib\site-packages\aiohttp_retry\client.py:119 in _do_request │ │ │ │ 116 │ │ │ │ except IndexError: │ │ 117 │ │ │ │ │ params = self._params_list[-1] │ │ 118 │ │ │ │ │ │ > 119 │ │ │ │ response: ClientResponse = await self._request_func( │ │ 120 │ │ │ │ │ params.method, │ │ 121 │ │ │ │ │ params.url, │ │ 122 │ │ │ │ │ headers=params.headers, │ │ │ │ O:\Python314\Lib\site-packages\aiohttp\client.py:858 in _request │ │ │ │ 855 │ │ │ │ │ │ handler = _connect_and_send_request │ │ 856 │ │ │ │ │ │ │ 857 │ │ │ │ │ try: │ │ > 858 │ │ │ │ │ │ resp = await handler(req) │ │ 859 │ │ │ │ │ # Client connector errors should not be retried │ │ 860 │ │ │ │ │ except ( │ │ 861 │ │ │ │ │ │ ConnectionTimeoutError, │ │ │ │ O:\Python314\Lib\site-packages\aiohttp\client.py:812 in _connect_and_send_request │ │ │ │ 809 │ │ │ │ │ │ # connection timeout │ │ 810 │ │ │ │ │ │ assert self._connector is not None │ │ 811 │ │ │ │ │ │ try: │ │ > 812 │ │ │ │ │ │ │ conn = await self._connector.connect( │ │ 813 │ │ │ │ │ │ │ │ req, traces=traces, timeout=real_timeout │ │ 814 │ │ │ │ │ │ │ ) │ │ 815 │ │ │ │ │ │ except asyncio.TimeoutError as exc: │ │ │ │ O:\Python314\Lib\site-packages\aiohttp\connector.py:657 in connect │ │ │ │ 654 │ │ │ │ if traces: │ │ 655 │ │ │ │ │ for trace in traces: │ │ 656 │ │ │ │ │ │ await trace.send_connection_create_start() │ │ > 657 │ │ │ │ proto = await self._create_connection(req, traces, timeout) │ │ 658 │ │ │ │ if traces: │ │ 659 │ │ │ │ │ for trace in traces: │ │ 660 │ │ │ │ │ │ await trace.send_connection_create_end() │ │ │ │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1242 in _create_connection │ │ │ │ 1239 │ │ if req.proxy: │ │ 1240 │ │ │ _, proto = await self._create_proxy_connection(req, traces, timeout) │ │ 1241 │ │ else: │ │ > 1242 │ │ │ _, proto = await self._create_direct_connection(req, traces, timeout) │ │ 1243 │ │ │ │ 1244 │ │ return proto │ │ 1245 │ │ │ │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1620 in _create_direct_connection │ │ │ │ 1617 │ │ │ return transp, proto │ │ 1618 │ │ else: │ │ 1619 │ │ │ assert last_exc is not None │ │ > 1620 │ │ │ raise last_exc │ │ 1621 │ │ │ 1622 │ async def _create_proxy_connection( │ │ 1623 │ │ self, req: ClientRequest, traces: list["Trace"], timeout: "ClientTimeout" │ │ │ │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1589 in _create_direct_connection │ │ │ │ 1586 │ │ │ ) │ │ 1587 │ │ │ │ │ 1588 │ │ │ try: │ │ > 1589 │ │ │ │ transp, proto = await self._wrap_create_connection( │ │ 1590 │ │ │ │ │ self._factory, │ │ 1591 │ │ │ │ │ timeout=timeout, │ │ 1592 │ │ │ │ │ ssl=sslcontext, │ │ │ │ O:\Python314\Lib\site-packages\aiohttp\connector.py:1318 in _wrap_create_connection │ │ │ │ 1315 │ │ │ │ │ kwargs["ssl_shutdown_timeout"] = self._ssl_shutdown_timeout │ │ 1316 │ │ │ │ return await self._loop.create_connection(*args, **kwargs, sock=sock) │ │ 1317 │ │ except cert_errors as exc: │ │ > 1318 │ │ │ raise ClientConnectorCertificateError(req.connection_key, exc) from exc │ │ 1319 │ │ except ssl_errors as exc: │ │ 1320 │ │ │ raise ClientConnectorSSLError(req.connection_key, exc) from exc │ │ 1321 │ │ except OSError as exc: │ └──────────────────────────────────────────────────────────────────────────────────────────────────┘ ClientConnectorCertificateError: Cannot connect to host api.boosty.to:443 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:1082)')] [20:06:11] INFO Boosty_Downloader.INFO 🔹: Details written to boosty-downloader-debug.log - attach it to the issue. ```
bsakaguchi 2026-10-13 19:46:04 +00:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@print423 commented on GitHub (Aug 31, 2026):

Maybe this will be helpful to someone.
I downloaded cacert.pem from the official website, then passed it to Python and ran the script (the contents of the batch file are shown below), after which the script started working.

@echo off
set SSL_CERT_FILE=O:\Python314\Scripts\cacert.pem
set REQUESTS_CA_BUNDLE=O:\Python314\Scripts\cacert.pem
boosty-downloader.exe download --username [author_name]
pause

<!-- gh-comment-id:5474285357 --> @print423 commented on GitHub (Aug 31, 2026): Maybe this will be helpful to someone. I downloaded cacert.pem from the official website, then passed it to Python and ran the script (the contents of the batch file are shown below), after which the script started working. @echo off set SSL_CERT_FILE=O:\Python314\Scripts\cacert.pem set REQUESTS_CA_BUNDLE=O:\Python314\Scripts\cacert.pem boosty-downloader.exe download --username [author_name] pause
Author
Owner

@Glitchy-Sheep commented on GitHub (Aug 31, 2026):

Interesting, I'll check this out a little bit later, thank you very much

<!-- gh-comment-id:5478546136 --> @Glitchy-Sheep commented on GitHub (Aug 31, 2026): Interesting, I'll check this out a little bit later, thank you very much
Author
Owner

@Glitchy-Sheep commented on GitHub (Oct 3, 2026):

@print423

Just to confirm: did the connection fail with the default settings, then work after you set SSL_CERT_FILE to cacert.pem?

On Windows, Python uses CA certificates from the Windows certificate stores and OpenSSL's default paths. The error does not tell us which certificate had expired.

Where did you download cacert.pem? Was it https://curl.se/ca/cacert.pem?

If the problem still occurs without the workaround:

  1. Check your system date and time.

  2. Press Win + R and open these separately:

    certmgr.msc
    
    certlm.msc
    

    These show user and computer certificates. Under Trusted Root Certification Authorities and Intermediate Certification Authorities, open Certificates and check the validity dates. Please leave the certificates unchanged; an expired entry alone does not prove it caused the error.

  3. In Command Prompt, check the certificate trust list:

    certutil -verifyCTL AuthRoot
    

Please share any errors and the LastSyncTime value from the output.

<!-- gh-comment-id:5972253215 --> @Glitchy-Sheep commented on GitHub (Oct 3, 2026): @print423 Just to confirm: did the connection fail with the default settings, then work after you set `SSL_CERT_FILE` to `cacert.pem`? On Windows, Python uses CA certificates from the Windows certificate stores and OpenSSL's default paths. The error does not tell us which certificate had expired. Where did you download `cacert.pem`? Was it https://curl.se/ca/cacert.pem? If the problem still occurs without the workaround: 1. Check your system date and time. 2. Press `Win + R` and open these separately: ```text certmgr.msc ``` ```text certlm.msc ``` These show user and computer certificates. Under **Trusted Root Certification Authorities** and **Intermediate Certification Authorities**, open **Certificates** and check the validity dates. Please leave the certificates unchanged; an expired entry alone does not prove it caused the error. 3. In Command Prompt, check the certificate trust list: ```bat certutil -verifyCTL AuthRoot ``` Please share any errors and the `LastSyncTime` value from the output.
Author
Owner

@Glitchy-Sheep commented on GitHub (Oct 3, 2026):

Since providing a fresh CA bundle resolved the issue for you, I'm closing this for now. Current tests also pass with certificate verification enabled. Please reopen the issue if it happens again.

<!-- gh-comment-id:5972304549 --> @Glitchy-Sheep commented on GitHub (Oct 3, 2026): Since providing a fresh CA bundle resolved the issue for you, I'm closing this for now. Current tests also pass with certificate verification enabled. Please reopen the issue if it happens again.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Glitchy-Sheep/boosty-downloader#29
No description provided.