diff --git a/keyserver/src/services/blob.js b/keyserver/src/services/blob.js
--- a/keyserver/src/services/blob.js
+++ b/keyserver/src/services/blob.js
@@ -3,8 +3,8 @@
 import blobService from 'lib/facts/blob-service.js';
 import type { BlobHashAndHolder } from 'lib/types/holder-types.js';
 import {
-  getBlobFetchableURL,
   makeBlobServiceEndpointURL,
+  downloadBlob,
 } from 'lib/utils/blob-service.js';
 import {
   uploadBlob,
@@ -112,17 +112,13 @@
       +blob: Blob,
     };
 async function download(hash: string): Promise<BlobDownloadResult> {
-  const url = getBlobFetchableURL(hash);
   const headers = await createRequestHeaders();
-  const response = await fetch(url, {
-    method: blobService.httpEndpoints.GET_BLOB.method,
-    headers,
-  });
+  const blobResult = await downloadBlob(hash, headers);
 
-  if (!response.ok) {
-    return { found: false, status: response.status };
+  if (blobResult.result !== 'success') {
+    return { found: false, status: blobResult.status };
   }
-  const blob = await response.blob();
+  const blob = await blobResult.response.blob();
   return { found: true, blob };
 }
 
diff --git a/lib/components/base-auto-join-community-handler.react.js b/lib/components/base-auto-join-community-handler.react.js
--- a/lib/components/base-auto-join-community-handler.react.js
+++ b/lib/components/base-auto-join-community-handler.react.js
@@ -5,7 +5,6 @@
 import * as React from 'react';
 
 import { NeynarClientContext } from './neynar-client-provider.react.js';
-import blobService from '../facts/blob-service.js';
 import { useIsLoggedInToIdentityAndAuthoritativeKeyserver } from '../hooks/account-hooks.js';
 import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js';
 import {
@@ -22,7 +21,7 @@
 import type { CalendarQuery } from '../types/entry-types.js';
 import type { SetState } from '../types/hook-types.js';
 import { defaultThreadSubscription } from '../types/subscription-types.js';
-import { getBlobFetchableURL } from '../utils/blob-service.js';
+import { downloadBlob } from '../utils/blob-service.js';
 import { useCurrentUserFID } from '../utils/farcaster-utils.js';
 import { promiseAll } from '../utils/promises.js';
 import { useSelector } from '../utils/redux-utils.js';
@@ -126,18 +125,13 @@
       for (const channelID of followedFarcasterChannelIDs) {
         promises[channelID] = (async () => {
           const blobHash = farcasterChannelTagBlobHash(channelID);
-          const blobURL = getBlobFetchableURL(blobHash);
-
-          const blobResult = await fetch(blobURL, {
-            method: blobService.httpEndpoints.GET_BLOB.method,
-            headers,
-          });
-
-          if (blobResult.status !== 200) {
+          const blobResult = await downloadBlob(blobHash, headers);
+          if (blobResult.result !== 'success') {
             return null;
           }
 
-          const { commCommunityID, keyserverURL } = await blobResult.json();
+          const { commCommunityID, keyserverURL } =
+            await blobResult.response.json();
           const keyserverID = extractKeyserverIDFromID(commCommunityID);
 
           // The user is already in the community
diff --git a/lib/shared/invite-links.js b/lib/shared/invite-links.js
--- a/lib/shared/invite-links.js
+++ b/lib/shared/invite-links.js
@@ -1,8 +1,7 @@
 // @flow
 
 import type { AuthMetadata } from './identity-client-context.js';
-import blobService from '../facts/blob-service.js';
-import { getBlobFetchableURL } from '../utils/blob-service.js';
+import { downloadBlob } from '../utils/blob-service.js';
 import { createDefaultHTTPRequestHeaders } from '../utils/services-utils.js';
 
 function inviteLinkBlobHash(secret: string): string {
@@ -18,18 +17,16 @@
   secret: string,
   authMetadata?: AuthMetadata,
 ): Promise<?KeyserverOverride> {
-  const blobURL = getBlobFetchableURL(inviteLinkBlobHash(secret));
   const headers = authMetadata
     ? createDefaultHTTPRequestHeaders(authMetadata)
     : {};
-  const result = await fetch(blobURL, {
-    method: blobService.httpEndpoints.GET_BLOB.method,
-    headers,
-  });
-  if (result.status !== 200) {
+
+  const blobResult = await downloadBlob(inviteLinkBlobHash(secret), headers);
+  if (blobResult.result !== 'success') {
     return null;
   }
-  const resultText = await result.text();
+
+  const resultText = await blobResult.response.text();
   const resultObject = JSON.parse(resultText);
   if (resultObject.keyserverID && resultObject.keyserverURL) {
     const keyserverURL: string = resultObject.keyserverURL;
diff --git a/lib/utils/blob-service.js b/lib/utils/blob-service.js
--- a/lib/utils/blob-service.js
+++ b/lib/utils/blob-service.js
@@ -83,6 +83,29 @@
       +statusText: string,
     };
 
+export type BlobDownloadResult =
+  | { +result: 'success', response: Response }
+  | { +result: 'error', +status: number, +statusText: string };
+
+async function downloadBlob(
+  blobHash: string,
+  headers: { [string]: string },
+): Promise<BlobDownloadResult> {
+  const blobURL = getBlobFetchableURL(blobHash);
+
+  const response = await fetch(blobURL, {
+    method: blobServiceConfig.httpEndpoints.GET_BLOB.method,
+    headers,
+  });
+
+  if (response.status !== 200) {
+    const { status, statusText } = response;
+    return { result: 'error', status, statusText };
+  }
+
+  return { result: 'success', response };
+}
+
 async function uploadBlob(
   blob: Blob | string,
   hash: string,
@@ -218,6 +241,7 @@
   generateBlobHolder,
   getBlobFetchableURL,
   makeBlobServiceEndpointURL,
+  downloadBlob,
   uploadBlob,
   assignMultipleHolders,
   removeMultipleHolders,