diff --git a/src/data_transfer.cpp b/src/data_transfer.cpp
index 4d0371a7e5980ce00c9b45709044fae7e209f0fd..8b75209978b7fa6e92b88fa2d90988241e548040 100644
--- a/src/data_transfer.cpp
+++ b/src/data_transfer.cpp
@@ -203,21 +203,16 @@ IncomingFile::process()
         auto shared = w.lock();
         if (!shared)
             return;
-        auto isEOF = shared->info_.bytesProgress == shared->info_.totalSize;
-        if (shared->stream_ && shared->stream_.is_open()) {
-            isEOF |= shared->stream_.eof();
-            shared->stream_.close();
-        }
-        auto correct = isEOF && shared->sha3Sum_.empty();
-        if (!correct && !shared->sha3Sum_.empty()) {
+        auto correct = shared->sha3Sum_.empty();
+        if (!correct) {
             // Verify shaSum
             auto sha3Sum = fileutils::sha3File(shared->info_.path);
-            if (shared->sha3Sum_ == sha3Sum) {
-                JAMI_INFO() << "New file received: " << shared->info_.path;
-                correct = true;
-            } else if (isEOF || shared->isUserCancelled_) {
+            if (shared->isUserCancelled_) {
                 JAMI_WARN() << "Remove file, invalid sha3sum detected for " << shared->info_.path;
                 fileutils::remove(shared->info_.path, true);
+            } else if (shared->sha3Sum_ == sha3Sum) {
+                JAMI_INFO() << "New file received: " << shared->info_.path;
+                correct = true;
             } else {
                 JAMI_WARN() << "Invalid sha3sum detected, unfinished file: " << shared->info_.path;
             }
@@ -486,12 +481,17 @@ TransferManager::path(const std::string& fileId) const
 }
 
 void
-TransferManager::onIncomingProfile(const std::shared_ptr<ChannelSocket>& channel)
+TransferManager::onIncomingProfile(const std::shared_ptr<ChannelSocket>& channel, const std::string& sha3Sum)
 {
     if (!channel)
         return;
 
     auto name = channel->name();
+    auto sep = name.find_last_of('?');
+    std::string arguments;
+    if (sep != std::string::npos)
+        name = name.substr(0, sep);
+
     auto lastSep = name.find_last_of('/');
     auto fileId = name.substr(lastSep + 1);
 
@@ -521,7 +521,7 @@ TransferManager::onIncomingProfile(const std::shared_ptr<ChannelSocket>& channel
     fileutils::recursive_mkdir(recvDir);
     info.path =  fmt::format("{:s}{:s}_{:s}_{}", recvDir, deviceId, uri, tid);
 
-    auto ifile = std::make_shared<IncomingFile>(std::move(channel), info, "profile.vcf", "");
+    auto ifile = std::make_shared<IncomingFile>(std::move(channel), info, "profile.vcf", "", sha3Sum);
     auto res = pimpl_->vcards_.emplace(idx, std::move(ifile));
     if (res.second) {
         res.first->second->onFinished([w = weak(),
diff --git a/src/data_transfer.h b/src/data_transfer.h
index ffb84d360fd939767b498dc627634f4f01839ed8..89fc10a07433922f212c5e24152f94c47dd7ec15 100644
--- a/src/data_transfer.h
+++ b/src/data_transfer.h
@@ -195,7 +195,7 @@ public:
      */
     std::vector<WaitingRequest> waitingRequests() const;
     bool isWaiting(const std::string& fileId) const;
-    void onIncomingProfile(const std::shared_ptr<ChannelSocket>& channel);
+    void onIncomingProfile(const std::shared_ptr<ChannelSocket>& channel, const std::string& sha3Sum = "");
 
     /**
      * @param contactId     contact's id
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 11ff5685891f1788da88505cc0cb5b87ba6e54d8..0a90cdba6929f09145da9db4495d715d854db9d0 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -3678,13 +3678,16 @@ JamiAccount::requestSIPConnection(const std::string& peerId,
 void
 JamiAccount::sendProfile(const std::string& convId, const std::string& peerUri, const std::string& deviceId)
 {
+    if (not fileutils::isFile(fmt::format("{}/profile.vcf", idPath_)))
+        return;
+    auto currentSha3 = fileutils::sha3File(fmt::format("{}/profile.vcf", idPath_));
     // VCard sync for peerUri
-    if (not needToSendProfile(peerUri, deviceId)) {
+    if (not needToSendProfile(peerUri, deviceId, currentSha3)) {
         JAMI_DEBUG("Peer {} already got an up-to-date vcard", peerUri);
         return;
     }
     // We need a new channel
-    transferFile(convId, profilePath(), deviceId, "profile.vcf", "", 0, 0, std::move([accId = getAccountID(), peerUri, deviceId]() {
+    transferFile(convId, profilePath(), deviceId, "profile.vcf", "", 0, 0, currentSha3, std::move([accId = getAccountID(), peerUri, deviceId]() {
         // Mark the VCard as sent
         auto sendDir = fmt::format("{}/{}/vcard/{}",
                                     fileutils::get_cache_dir(),
@@ -3700,9 +3703,8 @@ JamiAccount::sendProfile(const std::string& convId, const std::string& peerUri,
 }
 
 bool
-JamiAccount::needToSendProfile(const std::string& peerUri, const std::string& deviceId)
+JamiAccount::needToSendProfile(const std::string& peerUri, const std::string& deviceId, const std::string& sha3Sum)
 {
-    auto currentSha3 = fileutils::sha3File(fmt::format("{}/profile.vcf", idPath_));
     std::string previousSha3 {};
     auto vCardPath = fmt::format("{}/vcard", cachePath_);
     auto sha3Path = fmt::format("{}/sha3", vCardPath);
@@ -3710,14 +3712,14 @@ JamiAccount::needToSendProfile(const std::string& peerUri, const std::string& de
     try {
         previousSha3 = fileutils::loadTextFile(sha3Path);
     } catch (...) {
-        fileutils::saveFile(sha3Path, {currentSha3.begin(), currentSha3.end()}, 0600);
+        fileutils::saveFile(sha3Path, {sha3Sum.begin(), sha3Sum.end()}, 0600);
         return true;
     }
-    if (currentSha3 != previousSha3) {
+    if (sha3Sum != previousSha3) {
         // Incorrect sha3 stored. Update it
         fileutils::removeAll(vCardPath, true);
         fileutils::check_dir(vCardPath.c_str(), 0700);
-        fileutils::saveFile(sha3Path, {currentSha3.begin(), currentSha3.end()}, 0600);
+        fileutils::saveFile(sha3Path, {sha3Sum.begin(), sha3Sum.end()}, 0600);
         return true;
     }
     fileutils::recursive_mkdir(fmt::format("{}/{}/", vCardPath, peerUri));
@@ -4000,14 +4002,19 @@ JamiAccount::transferFile(const std::string& conversationId,
                           const std::string& interactionId,
                           size_t start,
                           size_t end,
+                          const std::string& sha3Sum,
                           std::function<void()> onFinished)
 {
-    auto channelName = conversationId.empty() ? fmt::format("{}profile.vcf", DATA_TRANSFER_URI)
+    auto fid = fileId;
+    if (fid == "profile.vcf") {
+        fid =  fmt::format("profile.vcf?sha3={}", sha3Sum);
+    }
+    auto channelName = conversationId.empty() ? fmt::format("{}profile.vcf?sha3={}", DATA_TRANSFER_URI, sha3Sum)
                         : fmt::format("{}{}/{}/{}",
                                    DATA_TRANSFER_URI,
                                    conversationId,
                                    currentDeviceId(),
-                                   fileId);
+                                   fid);
     std::lock_guard<std::mutex> lkCM(connManagerMtx_);
     if (!connectionManager_)
         return;
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index d3dda1f04a92bb90bd55ccc6cf88d4bb5d7be3ce..f1a5aa1d085b8a8d5c2e8f8dea5e78b7d6c01f7c 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -520,6 +520,7 @@ public:
                       const std::string& interactionId,
                       size_t start = 0,
                       size_t end = 0,
+                      const std::string& sha3Sum = "",
                       std::function<void()> onFinished = {});
 
     void askForFileChannel(const std::string& conversationId,
@@ -547,9 +548,10 @@ public:
      * Check (via the cache) if we need to send our profile to a specific device
      * @param peerUri       Uri that will receive the profile
      * @param deviceId      Device that will receive the profile
+     * @param sha3Sum       SHA3 hash of the profile
      */
     // Note: when swarm will be merged, this can be moved in transferManager
-    bool needToSendProfile(const std::string& peerUri, const std::string& deviceId);
+    bool needToSendProfile(const std::string& peerUri, const std::string& deviceId, const std::string& sha3Sum);
     /**
      * Send Profile via cached SIP connection
      * @param convId        Conversation's identifier (can be empty for self profile on sync)
diff --git a/src/jamidht/transfer_channel_handler.cpp b/src/jamidht/transfer_channel_handler.cpp
index e9c905fd2fd3c6ea9ca19e2ae1a0f2d0807d54a3..7eca025f3d626e8340b31981332bde4b25845cf0 100644
--- a/src/jamidht/transfer_channel_handler.cpp
+++ b/src/jamidht/transfer_channel_handler.cpp
@@ -54,11 +54,14 @@ TransferChannelHandler::onRequest(const std::shared_ptr<dht::crypto::Certificate
     auto uri = cert->issuer->getId().toString();
     // Else, check if it's a profile or file in a conversation.
     auto idstr = name.substr(16);
+    // Remove arguments for now
+    auto sep = idstr.find_last_of('?');
+    idstr = idstr.substr(0, sep);
     if (idstr == "profile.vcf") {
         // If it's our profile from another device
         return uri == acc->getUsername();
     }
-    auto sep = idstr.find('/');
+    sep = idstr.find('/');
     auto lastSep = idstr.find_last_of('/');
     auto conversationId = idstr.substr(0, sep);
     auto fileHost = idstr.substr(sep + 1, lastSep - sep - 1);
@@ -66,11 +69,6 @@ TransferChannelHandler::onRequest(const std::shared_ptr<dht::crypto::Certificate
     if (fileHost == acc->currentDeviceId())
         return false;
 
-    sep = fileId.find_last_of('?');
-    if (sep != std::string::npos) {
-        fileId = fileId.substr(0, sep);
-    }
-
     // Check if peer is member of the conversation
     if (fileId == fmt::format("{}.vcf", acc->getUsername()) || fileId == "profile.vcf") {
         // Or a member from the conversation
@@ -98,9 +96,33 @@ TransferChannelHandler::onReady(const std::shared_ptr<dht::crypto::Certificate>&
         return;
 
     auto idstr = name.substr(16);
+    // Parse arguments
+    auto sep = idstr.find_last_of('?');
+    std::string arguments;
+    if (sep != std::string::npos) {
+        arguments = idstr.substr(sep + 1);
+        idstr = idstr.substr(0, sep);
+    }
+
+    auto start = 0u, end = 0u;
+    std::string sha3Sum;
+    for (const auto arg : split_string(arguments, '&')) {
+        auto keyVal = split_string(arg, '=');
+        if (keyVal.size() == 2) {
+            if (keyVal[0] == "start") {
+                start = to_int<unsigned>(keyVal[1]);
+            } else if (keyVal[0] == "end") {
+                end = to_int<unsigned>(keyVal[1]);
+            } else if (keyVal[0] == "sha3") {
+                sha3Sum = keyVal[1];
+            }
+        }
+    }
+
+    // Check if profile
     if (idstr == "profile.vcf") {
         if (!channel->isInitiator()) {
-            acc->dataTransfer()->onIncomingProfile(channel);
+            acc->dataTransfer()->onIncomingProfile(channel, sha3Sum);
         } else {
             // If it's a profile from sync
             std::string path = fmt::format("{}/profile.vcf", idPath_);
@@ -124,13 +146,6 @@ TransferChannelHandler::onReady(const std::shared_ptr<dht::crypto::Certificate>&
     if (channel->isInitiator())
         return;
 
-    auto sep = fileId.find_last_of('?');
-    std::string arguments;
-    if (sep != std::string::npos) {
-        arguments = fileId.substr(sep + 1);
-        fileId = fileId.substr(0, sep);
-    }
-
     // Profile for a member in the conversation
     if (fileId == fmt::format("{}.vcf", acc->getUsername())) {
         std::string path = fmt::format("{}/profile.vcf", idPath_);
@@ -141,7 +156,7 @@ TransferChannelHandler::onReady(const std::shared_ptr<dht::crypto::Certificate>&
         acc->dataTransfer()->transferFile(channel, fileId, "", path);
         return;
     } else if (fileId == "profile.vcf") {
-        acc->dataTransfer()->onIncomingProfile(channel);
+        acc->dataTransfer()->onIncomingProfile(channel, sha3Sum);
         return;
     }
     // Check if it's a file in a conversation
@@ -153,18 +168,6 @@ TransferChannelHandler::onReady(const std::shared_ptr<dht::crypto::Certificate>&
     }
     auto interactionId = fileId.substr(0, sep);
     std::string path = dt->path(fileId);
-    auto start = 0u, end = 0u;
-    for (const auto arg : split_string(arguments, '&')) {
-        auto keyVal = split_string(arg, '=');
-        if (keyVal.size() == 2) {
-            if (keyVal[0] == "start") {
-                start = to_int<unsigned>(keyVal[1]);
-            } else if (keyVal[0] == "end") {
-                end = to_int<unsigned>(keyVal[1]);
-            }
-        }
-    }
-
     dt->transferFile(channel, fileId, interactionId, path, start, end);
 }