diff --git a/src/input/AsyncInputStream.cxx b/src/input/AsyncInputStream.cxx
index 68cb8ff..df37104 100644
--- a/src/input/AsyncInputStream.cxx
+++ b/src/input/AsyncInputStream.cxx
@@ -155,6 +155,20 @@ AsyncInputStream::Seek(offset_type new_offset, Error &error)
 }
 
 void
+AsyncInputStream::SeekStart()
+{
+	assert(io_thread_inside());
+	assert(IsSeekPending());
+
+	/* we may have reached end-of-file previously, and the
+	   connection may have been closed already; however after
+	   seeking successfully, the connection must be alive again */
+	open = true;
+
+	seek_state = SeekState::PENDING;
+}
+
+void
 AsyncInputStream::SeekDone()
 {
 	assert(io_thread_inside());
diff --git a/src/input/AsyncInputStream.hxx b/src/input/AsyncInputStream.hxx
index 64f566a..1ce1716 100644
--- a/src/input/AsyncInputStream.hxx
+++ b/src/input/AsyncInputStream.hxx
@@ -154,6 +154,7 @@ protected:
 	 * Call this after seeking has finished.  It will notify the
 	 * client thread.
 	 */
+	void SeekStart();
 	void SeekDone();
 
 private:
diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx
index 814fe7a..2745e9d 100644
--- a/src/input/plugins/CurlInputPlugin.cxx
+++ b/src/input/plugins/CurlInputPlugin.cxx
@@ -81,7 +81,7 @@ struct CurlInputStream final : public AsyncInputStream {
 				  _buffer, CURL_MAX_BUFFERED,
 				  CURL_RESUME_AT),
 		 request_headers(nullptr),
-		 icy(new IcyInputStream(this)) {}
+		 icy(new IcyInputStream(this)), try_count(0), read_bytes(0) {}
 
 	~CurlInputStream();
 
@@ -130,6 +130,13 @@ struct CurlInputStream final : public AsyncInputStream {
 	/* virtual methods from AsyncInputStream */
 	virtual void DoResume() override;
 	virtual void DoSeek(offset_type new_offset) override;
+
+private:
+	void DoSeekInternal(offset_type new_offset);
+
+	/** connection try count */
+	int try_count;
+	offset_type read_bytes;
 };
 
 class CurlMulti;
@@ -297,7 +304,9 @@ CurlInputStream::DoResume()
 
 	mutex.unlock();
 
-	curl_easy_pause(easy, CURLPAUSE_CONT);
+	if (easy != nullptr) {
+		curl_easy_pause(easy, CURLPAUSE_CONT);
+	}
 
 	if (curl_version_num < 0x072000)
 		/* libcurl older than 7.32.0 does not update
@@ -441,8 +450,16 @@ CurlInputStream::RequestDone(CURLcode result, long status)
 	const ScopeLock protect(mutex);
 
 	if (result != CURLE_OK) {
-		postponed_error.Format(curl_domain, result,
+		/* when network is bad, we need to try one more times */
+		if (try_count++ < 3) {
+			SeekStart();
+			DoSeekInternal(read_bytes);
+			cond.broadcast();
+			return;
+		} else  {
+			postponed_error.Format(curl_domain, result,
 				       "curl failed: %s", error_buffer);
+		}
 	} else if (status < 200 || status >= 300) {
 		postponed_error.Format(http_domain, status,
 				       "got HTTP status %ld",
@@ -711,8 +728,10 @@ CurlInputStream::DataReceived(const void *ptr, size_t received_size)
 
 	const ScopeLock protect(mutex);
 
-	if (IsSeekPending())
+	if (IsSeekPending()) {
+		try_count = 0;
 		SeekDone();
+	}
 
 	if (received_size > GetBufferSpace()) {
 		AsyncInputStream::Pause();
@@ -720,6 +739,7 @@ CurlInputStream::DataReceived(const void *ptr, size_t received_size)
 	}
 
 	AppendToBuffer(ptr, received_size);
+	read_bytes += received_size;
 	return received_size;
 }
 
@@ -800,6 +820,15 @@ CurlInputStream::InitEasy(Error &error)
 void
 CurlInputStream::DoSeek(offset_type new_offset)
 {
+	try_count = 0;
+	read_bytes = new_offset;
+
+	DoSeekInternal(new_offset);
+}
+
+void
+CurlInputStream::DoSeekInternal(offset_type new_offset)
+{
 	assert(IsReady());
 
 	/* close the old connection and open a new one */
