diff --git a/packages/shared/components/MediaDisplay.svelte b/packages/shared/components/MediaDisplay.svelte
index 8df73db2c8a..d08e9111b20 100644
--- a/packages/shared/components/MediaDisplay.svelte
+++ b/packages/shared/components/MediaDisplay.svelte
@@ -31,7 +31,7 @@
 </script>
 
 <div class="h-full w-full object-cover">
-    {#if htmlTag === ParentMimeType.Image}
+    {#if htmlTag === ParentMimeType.Image || htmlTag === ParentMimeType.Text}
         <img {src} {alt} loading="lazy" class="w-full h-full object-cover" />
     {:else if htmlTag === ParentMimeType.Video}
         <video
diff --git a/packages/shared/components/NftImageOrIconBox.svelte b/packages/shared/components/NftImageOrIconBox.svelte
index c821731dc24..a1c9b5dd1ad 100644
--- a/packages/shared/components/NftImageOrIconBox.svelte
+++ b/packages/shared/components/NftImageOrIconBox.svelte
@@ -1,8 +1,7 @@
 <script lang="ts">
-    import { INft } from '@core/nfts'
-    import { NftSize } from 'shared/components/enums'
+    import { INft, ParentMimeType } from '@core/nfts'
     import { MediaPlaceholder, NftMedia } from 'shared/components'
-    import { ParentMimeType } from '@core/nfts'
+    import { NftSize } from 'shared/components/enums'
 
     export let nft: INft | null = null
     export let size: NftSize = NftSize.Medium
@@ -18,7 +17,7 @@
     class:medium={size === NftSize.Medium}
     class:large={size === NftSize.Large}
 >
-    {#if parentType === ParentMimeType.Image && nft}
+    {#if (parentType === ParentMimeType.Image && nft) || (parentType === ParentMimeType.Text && nft)}
         <NftMedia {nft} {useCaching}>
             <placeholder-wrapper
                 slot="placeholder"
diff --git a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
index e67fa150a36..33a18312c13 100644
--- a/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
+++ b/packages/shared/lib/core/nfts/actions/downloadNextNftInQueue.ts
@@ -1,6 +1,7 @@
 import { Platform } from '@core/app'
 import { get } from 'svelte/store'
 import { downloadingNftId, nftDownloadQueue, removeNftFromDownloadQueue } from '../stores'
+import { getIpfsUri, getIPFSHash } from '../utils'
 
 export async function downloadNextNftInQueue(): Promise<void> {
     const nextDownload = get(nftDownloadQueue)?.[0]
@@ -9,8 +10,17 @@ export async function downloadNextNftInQueue(): Promise<void> {
     }
 
     try {
-        const { downloadUrl, path, nft, accountIndex } = nextDownload
+        // eslint-disable-next-line prefer-const
+        let { downloadUrl, path, nft, accountIndex } = nextDownload
         downloadingNftId.set(nft.id)
+        const ipfsHash = getIPFSHash(downloadUrl)
+        if (ipfsHash) {
+            const ipfsUri = await getIpfsUri({ hash: ipfsHash })
+            if (ipfsUri) {
+                downloadUrl = ipfsUri
+            }
+        }
+
         await Platform.downloadNft(downloadUrl, path, nft.id, accountIndex)
     } catch (error) {
         downloadingNftId.set(undefined)
diff --git a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
index 62f63dd2936..bd4214c2655 100644
--- a/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
+++ b/packages/shared/lib/core/nfts/actions/updateNftInAllAccountNfts.ts
@@ -1,5 +1,6 @@
-import { allAccountNfts } from '../stores'
 import { INft } from '../interfaces'
+import { allAccountNfts } from '../stores'
+import { getIpfsUri, getIPFSHash } from '../utils'
 
 export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, partialNft: Partial<INft>): void {
     allAccountNfts.update((state) => {
@@ -8,6 +9,16 @@ export function updateNftInAllAccountNfts(accountIndex: number, nftId: string, p
         }
         const nft = state[accountIndex].find((_nft) => _nft.id === nftId)
         if (nft) {
+            const downloadUrl = nft.downloadUrl
+            const ipfsHash = getIPFSHash(downloadUrl)
+            if (ipfsHash) {
+                void getIpfsUri({ hash: ipfsHash }).then((ipfsUri) => {
+                    if (ipfsUri) {
+                        nft.downloadUrl = ipfsUri
+                        nft.composedUrl = ipfsUri
+                    }
+                })
+            }
             Object.assign(nft, { ...nft, ...partialNft })
         }
         return state
diff --git a/packages/shared/lib/core/nfts/utils/getIpfsHash.ts b/packages/shared/lib/core/nfts/utils/getIpfsHash.ts
new file mode 100644
index 00000000000..44997e4cca8
--- /dev/null
+++ b/packages/shared/lib/core/nfts/utils/getIpfsHash.ts
@@ -0,0 +1,7 @@
+export function getIPFSHash(url?: string): string | undefined {
+    const ipfsPrefix = 'https://ipfs.io'
+
+    if (url?.includes(ipfsPrefix)) {
+        return url.slice(ipfsPrefix.length)
+    }
+}
diff --git a/packages/shared/lib/core/nfts/utils/getIpfsUri.ts b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
new file mode 100644
index 00000000000..3d094ea6a87
--- /dev/null
+++ b/packages/shared/lib/core/nfts/utils/getIpfsUri.ts
@@ -0,0 +1,152 @@
+interface IIpfsLink {
+    Hash: string
+    Name: string
+    Size: number
+    Target: string
+    Type: number
+    Mode?: string
+    Mtime?: number
+    MtimeNsecs?: number
+}
+
+interface IIPfsEntry {
+    readonly type: 'dir' | 'file'
+    readonly cid: string
+    readonly name: string
+    readonly path: string
+    mode?: number
+    mtime?: {
+        secs: number
+        nsecs?: number
+    }
+    size: number
+}
+
+interface IIpfsObject {
+    Hash: string
+    Links: IIpfsLink[]
+}
+
+enum typeOfLink {
+    Dir = 'dir',
+    File = 'file',
+}
+
+const IPFS_ENDPOINT = 'https://ipfs.io'
+const IPFS_PATH = '/api/v0/ls'
+const IPFS_PREFIX = '/ipfs/'
+
+export async function getIpfsUri(link: { path?: string; hash: string }): Promise<string | undefined> {
+    let ipfsLink = `${link.hash}${link.path ?? ''}`
+    try {
+        const ipfsEntry = await ls(ipfsLink)
+
+        if (ipfsEntry) {
+            if (ipfsEntry.type === 'dir') {
+                const path = `${link.path ?? ''}/${ipfsEntry.name}`
+                return await getIpfsUri({ hash: link.hash, path })
+            }
+            ipfsLink = `${ipfsLink}/${encodeURIComponent(ipfsEntry.name)}`
+        }
+    } catch (error) {
+        console.error('error', error)
+    }
+
+    return `${IPFS_ENDPOINT}${ipfsLink}`
+}
+
+async function ls(path: string): Promise<IIPfsEntry | undefined> {
+    let ipfsEntry: IIPfsEntry | undefined
+
+    try {
+        const baseUrl = IPFS_ENDPOINT
+        const method = 'get'
+        const payload = undefined
+        let headers = {}
+        const timeout = undefined
+
+        headers ??= {}
+
+        let controller: AbortController | undefined
+        let timerId: NodeJS.Timeout | undefined
+
+        if (timeout !== undefined) {
+            controller = new AbortController()
+            timerId = setTimeout(() => {
+                if (controller) {
+                    controller.abort()
+                }
+            }, timeout)
+        }
+
+        try {
+            if (path.includes('ipfs')) {
+                const response = await fetch(`${baseUrl}${IPFS_PATH}?arg=/${path}`, {
+                    method,
+                    headers,
+                    body: payload ? JSON.stringify(payload) : undefined,
+                    signal: controller ? controller.signal : undefined,
+                })
+                const lsResponse = (await response.json()) as { Objects: IIpfsObject[] }
+                const result = lsResponse.Objects[0]
+                if (result) {
+                    const links = result.Links
+                    if (links.length > 0) {
+                        ipfsEntry = mapLinkToIpfsEntry(links[0], path)
+                    }
+                }
+            }
+        } catch (error) {
+            console.error('error', error)
+        } finally {
+            if (timerId) {
+                clearTimeout(timerId)
+            }
+        }
+    } catch (error) {
+        console.error('error', error)
+    }
+
+    return ipfsEntry
+}
+
+function mapLinkToIpfsEntry(link: IIpfsLink, path: string): IIPfsEntry {
+    const hash = link.Hash.startsWith(IPFS_PREFIX) ? link.Hash.slice(IPFS_PREFIX.length) : link.Hash
+    const entry: IIPfsEntry = {
+        name: link.Name,
+        path: path + (link.Name ? `/${link.Name}` : ''),
+        size: link.Size,
+        cid: hash,
+        type: typeOf(link),
+    }
+    if (link.Mode) {
+        entry.mode = Number.parseInt(link.Mode, 8)
+    }
+
+    if (link.Mtime !== undefined && link.Mtime !== null) {
+        entry.mtime = {
+            secs: link.Mtime,
+        }
+
+        if (link.MtimeNsecs !== undefined && link.MtimeNsecs !== null) {
+            entry.mtime.nsecs = link.MtimeNsecs
+        }
+    }
+
+    return entry
+}
+
+function typeOf(link: IIpfsLink): typeOfLink {
+    switch (link.Type) {
+        case 1:
+        case 5: {
+            return typeOfLink.Dir
+        }
+        case 2: {
+            return typeOfLink.File
+        }
+        default: {
+            return typeOfLink.File
+        }
+    }
+}
diff --git a/packages/shared/lib/core/nfts/utils/index.ts b/packages/shared/lib/core/nfts/utils/index.ts
index ea8bd888dc2..717cbfe65c5 100644
--- a/packages/shared/lib/core/nfts/utils/index.ts
+++ b/packages/shared/lib/core/nfts/utils/index.ts
@@ -2,9 +2,11 @@ export * from './buildNftFromNftOutput'
 export * from './checkIfNftShouldBeDownloaded'
 export * from './composeUrlFromNftUri'
 export * from './convertAndFormatNftMetadata'
-export * from './getSpendableStatusFromUnspentNftOutput'
 export * from './fetchWithTimeout'
+export * from './getIpfsHash'
+export * from './getIpfsUri'
+export * from './getParentMimeType'
+export * from './getSpendableStatusFromUnspentNftOutput'
 export * from './isNftOwnedByAnyAccount'
 export * from './parseNftMetadata'
 export * from './rewriteIpfsUri'
-export * from './getParentMimeType'