diff --git a/components/brave_vpn/brave_vpn_service.cc b/components/brave_vpn/brave_vpn_service.cc
index c67641341246..c6b9d48ea350 100644
--- a/components/brave_vpn/brave_vpn_service.cc
+++ b/components/brave_vpn/brave_vpn_service.cc
@@ -80,6 +80,8 @@ BraveVpnService::~BraveVpnService() = default;
 
 void BraveVpnService::CheckInitialState() {
   if (HasValidSubscriberCredential(local_prefs_)) {
+    ScheduleSubscriberCredentialRefresh();
+
 #if BUILDFLAG(IS_ANDROID)
     SetPurchasedState(GetCurrentEnvironment(), PurchasedState::PURCHASED);
     // Android has its own region data managing logic.
@@ -725,6 +727,10 @@ void BraveVpnService::OnGetSubscriberCredentialV12(
 
   SetSubscriberCredential(local_prefs_, subscriber_credential, expiration_time);
 
+  // Launch one-shot timer for refreshing subscriber_credential before it's
+  // expired.
+  ScheduleSubscriberCredentialRefresh();
+
 #if BUILDFLAG(IS_ANDROID)
   SetPurchasedState(GetCurrentEnvironment(), PurchasedState::PURCHASED);
 #else
@@ -742,6 +748,30 @@ void BraveVpnService::OnGetSubscriberCredentialV12(
 #endif
 }
 
+void BraveVpnService::ScheduleSubscriberCredentialRefresh() {
+  if (subs_cred_refresh_timer_.IsRunning())
+    subs_cred_refresh_timer_.Stop();
+
+  const auto expiration_time = GetExpirationTime(local_prefs_);
+  if (!expiration_time)
+    return;
+
+  VLOG(2) << "Schedule subscriber credential fetching after "
+          << *expiration_time - base::Time::Now();
+  subs_cred_refresh_timer_.Start(
+      FROM_HERE, *expiration_time - base::Time::Now(),
+      base::BindOnce(&BraveVpnService::RefreshSubscriberCredential,
+                     base::Unretained(this)));
+}
+
+void BraveVpnService::RefreshSubscriberCredential() {
+  VLOG(2) << "Refresh subscriber credential";
+
+  // Clear current credentials to get newer one.
+  ClearSubscriberCredential(local_prefs_);
+  ReloadPurchasedState();
+}
+
 // TODO(simonhong): Should move p3a to BraveVPNOSConnectionAPI?
 void BraveVpnService::InitP3A() {
   p3a_timer_.Start(FROM_HERE, base::Hours(kP3AIntervalHours), this,
diff --git a/components/brave_vpn/brave_vpn_service.h b/components/brave_vpn/brave_vpn_service.h
index 68d364f41d0e..e4b4728929e1 100644
--- a/components/brave_vpn/brave_vpn_service.h
+++ b/components/brave_vpn/brave_vpn_service.h
@@ -217,6 +217,8 @@ class BraveVpnService :
   void OnGetSubscriberCredentialV12(const base::Time& expiration_time,
                                     const std::string& subscriber_credential,
                                     bool success);
+  void ScheduleSubscriberCredentialRefresh();
+  void RefreshSubscriberCredential();
 
   // Check initial purchased/connected state.
   void CheckInitialState();
@@ -247,6 +249,7 @@ class BraveVpnService :
   mojo::RemoteSet<mojom::ServiceObserver> observers_;
   BraveVpnAPIRequest api_request_;
   base::RepeatingTimer p3a_timer_;
+  base::OneShotTimer subs_cred_refresh_timer_;
   base::WeakPtrFactory<BraveVpnService> weak_ptr_factory_{this};
 };
 
diff --git a/components/brave_vpn/brave_vpn_service_helper.cc b/components/brave_vpn/brave_vpn_service_helper.cc
index 08de747505ba..abab091fbf23 100644
--- a/components/brave_vpn/brave_vpn_service_helper.cc
+++ b/components/brave_vpn/brave_vpn_service_helper.cc
@@ -19,7 +19,6 @@
 #include "brave/components/brave_vpn/pref_names.h"
 #include "brave/components/skus/browser/skus_utils.h"
 #include "components/prefs/pref_service.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
 
 namespace brave_vpn {
 
@@ -231,6 +230,22 @@ std::string GetSubscriberCredential(PrefService* local_prefs) {
   return *cred;
 }
 
+absl::optional<base::Time> GetExpirationTime(PrefService* local_prefs) {
+  if (!HasValidSubscriberCredential(local_prefs))
+    return absl::nullopt;
+
+  const base::Value::Dict& sub_cred_dict =
+      local_prefs->GetDict(prefs::kBraveVPNSubscriberCredential);
+
+  const base::Value* expiration_time_value =
+      sub_cred_dict.Find(kSubscriberCredentialExpirationKey);
+
+  if (!expiration_time_value)
+    return absl::nullopt;
+
+  return base::ValueToTime(expiration_time_value);
+}
+
 void SetSubscriberCredential(PrefService* local_prefs,
                              const std::string& subscriber_credential,
                              const base::Time& expiration_time) {
diff --git a/components/brave_vpn/brave_vpn_service_helper.h b/components/brave_vpn/brave_vpn_service_helper.h
index 2c5d7403018b..a66588c781f0 100644
--- a/components/brave_vpn/brave_vpn_service_helper.h
+++ b/components/brave_vpn/brave_vpn_service_helper.h
@@ -12,6 +12,7 @@
 
 #include "base/values.h"
 #include "brave/components/brave_vpn/mojom/brave_vpn.mojom.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
 
 class PrefService;
 
@@ -42,6 +43,7 @@ mojom::RegionPtr GetRegionPtrWithNameFromRegionList(
 bool IsValidCredentialSummary(const base::Value& summary);
 bool HasValidSubscriberCredential(PrefService* local_prefs);
 std::string GetSubscriberCredential(PrefService* local_prefs);
+absl::optional<base::Time> GetExpirationTime(PrefService* local_prefs);
 void SetSubscriberCredential(PrefService* local_prefs,
                              const std::string& subscriber_credential,
                              const base::Time& expiration_time);