diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b8b35a05faf7433b7ce7a90edf195216d60a317..8bcb20684652b58bc37fa046fbdaf7ef8a6dc3d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -366,6 +366,10 @@ IF(OTB_USE_CURL)
 
         INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
 
+        # TODO add test to check if curl multi is available
+        OPTION(OTB_CURL_MULTI_AVAILABLE "Whether or not the curl has curlmulti capabilities" ON)
+        MARK_AS_ADVANCED(OTB_CURL_MULTI_AVAILABLE)
+        ADD_DEFINITIONS(-DOTB_CURL_MULTI_AVAILABLE)
 ENDIF(OTB_USE_CURL)
 
 #-------------------------------
diff --git a/Code/IO/otbCurlHelper.cxx b/Code/IO/otbCurlHelper.cxx
index 720aa2aab2ba478738e0d438a639129d8db91652..660a3bb35dab2781607fe062a17d77bbc3bc8c59 100644
--- a/Code/IO/otbCurlHelper.cxx
+++ b/Code/IO/otbCurlHelper.cxx
@@ -17,7 +17,7 @@
 =========================================================================*/
 
 #include "otbCurlHelper.h"
-
+#include "otbMacro.h"
 
 #ifdef OTB_USE_CURL
 #include <curl/curl.h>
@@ -58,6 +58,11 @@ int CurlHelper::TestUrlAvailability(const std::string& url) const
 }
 
 int CurlHelper::RetrieveFile(const std::ostringstream& urlStream, std::string filename) const
+{
+  return RetrieveFile(urlStream.str(), filename);
+}
+
+int CurlHelper::RetrieveFile(const std::string& urlString, std::string filename) const
 {
 #ifdef OTB_USE_CURL
   CURL *   curl;
@@ -67,7 +72,7 @@ int CurlHelper::RetrieveFile(const std::ostringstream& urlStream, std::string fi
   curl = curl_easy_init();
 
   char url[256];
-  strcpy(url, urlStream.str().data());
+  strcpy(url, urlString.data());
 
 //   std::cout << url << std::endl;
   if (curl)
@@ -92,5 +97,183 @@ int CurlHelper::RetrieveFile(const std::ostringstream& urlStream, std::string fi
 #endif
 }
 
+
+int CurlHelper::RetrieveFileMulti(const std::vector<std::string>& listURLs, 
+                                  const std::vector<std::string>& listFilename,
+                                  int maxConnect) const
+{
+#ifdef OTB_USE_CURL
+#ifdef OTB_CURL_MULTI_AVAILABLE
+  otbMsgDevMacro(<< "Using curl multi");
+  std::string  m_Browser = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11";
+
+  CURLM *             multiHandle;
+  std::vector<CURL *> listCurlHandles;
+  std::vector<FILE *> listFiles;
+  
+  std::vector<std::string>::const_iterator filename;
+  filename = listFilename.begin();
+  while (filename != listFilename.end() )
+    {
+    FILE* lOutputFile = fopen((*filename).c_str(), "w");
+    if (lOutputFile == NULL)
+    {
+    itkExceptionMacro(<< "otbCurlHelper: bad file name: " << (*filename).c_str());
+    }
+
+    // Add file to vector
+    listFiles.push_back(lOutputFile);
+    ++filename;
+    }
+
+  // Initialize curl multi handle
+  multiHandle = curl_multi_init();
+
+  if (!multiHandle)
+    {
+    itkExceptionMacro(<< "otbCurlHelper: Curl multi handle init error.");
+    }
+
+  listCurlHandles.clear();
+
+  // Initialize curl handle
+
+  std::vector<std::string>::const_iterator url;
+  std::vector<FILE *>::const_iterator file;
+  url = listURLs.begin();
+  file = listFiles.begin();
+  while ( (url != listURLs.end()) && (file != listFiles.end() ))
+    {
+    CURL * lEasyHandle;
+    lEasyHandle = curl_easy_init();
+
+    if (!lEasyHandle)
+      {
+      itkExceptionMacro(<< "otbCurlHelper: Curl easy handle init error.");
+      }
+
+    // Param easy handle
+    curl_easy_setopt(lEasyHandle, CURLOPT_USERAGENT, m_Browser.data());
+    curl_easy_setopt(lEasyHandle, CURLOPT_URL, (*url).data());
+    curl_easy_setopt(lEasyHandle, CURLOPT_WRITEDATA, *file);
+
+    // Add easy handle to multi handle
+    curl_multi_add_handle(multiHandle, lEasyHandle);
+
+    // Add hanle to vector
+    listCurlHandles.push_back(lEasyHandle);
+    ++url;
+    ++file;
+    }
+
+//fetch tiles
+  // Configure multi handle - set the maximum connections
+  curl_multi_setopt(multiHandle, CURLMOPT_MAXCONNECTS, maxConnect);
+  curl_multi_setopt(multiHandle, CURLMOPT_PIPELINING, 0);
+
+  // Perform
+  int lStillRunning;
+
+  while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multiHandle, &lStillRunning));
+
+  // Now get that URL
+  while (lStillRunning)
+    {
+    struct timeval timeout;
+    int            rc; // Return code
+
+    fd_set fdread;
+    fd_set fdwrite;
+    fd_set fdexcep;
+    int    maxfd;
+
+    FD_ZERO(&fdread);
+    FD_ZERO(&fdwrite);
+    FD_ZERO(&fdexcep);
+
+    /* set a suitable timeout to play around with */
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 1;
+
+    /* get file descriptors from the transfers */
+    curl_multi_fdset(multiHandle, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    switch (rc)
+      {
+    case -1:
+      /* select error */
+      break;
+    case 0:
+    /* timeout */
+    default:
+      /* timeout or readable/writable sockets */
+      while (
+        CURLM_CALL_MULTI_PERFORM == curl_multi_perform(multiHandle, &lStillRunning)
+        )
+        ;
+      break;
+      }
+    }
+
+  int      remaining_msgs = 1;
+  int      error = 0;
+  CURLMsg *msg;
+  while (remaining_msgs)
+    {
+    msg = curl_multi_info_read(multiHandle, &remaining_msgs);
+    if (msg != NULL)
+      {
+      if (CURLE_OK != msg->data.result) error = 1;
+      }
+    }
+
+  if (error != 0)
+    {
+    itkExceptionMacro(<< "otbCurlHelper: Error occurs while perform Multi handle");
+    }
+
+
+// Cleanup
+
+  // Close files
+  for (unsigned int currentFile = 0; currentFile < listFiles.size(); currentFile++)
+    {
+    fclose(listFiles[currentFile]);
+    }
+  listFiles.clear();
+
+  // Cleanup easy handles
+  for (unsigned int currentHandle = 0; currentHandle < listCurlHandles.size(); currentHandle++)
+    {
+    curl_easy_cleanup(listCurlHandles[currentHandle]);
+    }
+  listCurlHandles.clear();
+
+  // Cleanup multi handle
+  curl_multi_cleanup(multiHandle);
+
+
+
+#else
+  //fallback on non curl multi
+  otbMsgDevMacro(<< "Curl multi is not available, fallback on standard");
+  std::vector<std::string>::const_iterator url;
+  std::vector<FILE *>::const_iterator file;
+  url = listURLs.begin();
+  file = listFiles.begin();
+  while ( (url != listURLs.end()) && (file != listFiles.end() ))
+    {
+    RetrieveFile(*url, *file);
+    }
+#endif
+#else
+  otbMsgDevMacro(<< "Curl is not available, compile with OTB_USE_CURL to ON");
+  return -1;
+#endif
+}
+
+
 }
 
diff --git a/Code/IO/otbCurlHelper.h b/Code/IO/otbCurlHelper.h
index b3152e6e2d5cbf6f0aa6ba9d8185f716184432ce..d535c496c5e435f6439b82b5773722ae07f2fcda 100644
--- a/Code/IO/otbCurlHelper.h
+++ b/Code/IO/otbCurlHelper.h
@@ -43,7 +43,11 @@ public:
 
   int TestUrlAvailability(const std::string& url) const;
   int RetrieveFile(const std::ostringstream& urlStream, std::string filename) const;
+  int RetrieveFile(const std::string& urlString, std::string filename) const;
 
+  int RetrieveFileMulti(const std::vector<std::string>& listURLs, 
+			const std::vector<std::string>& listFiles,
+                        int maxConnect) const;
 protected:
   CurlHelper() {}
   ~CurlHelper() {}
diff --git a/Code/IO/otbTileMapImageIO.cxx b/Code/IO/otbTileMapImageIO.cxx
index db38e270a4fc182986ac129542c5e3881bcf514a..0232a7046997b2fc79d1caf1c6d7a51700338b02 100644
--- a/Code/IO/otbTileMapImageIO.cxx
+++ b/Code/IO/otbTileMapImageIO.cxx
@@ -38,6 +38,8 @@
 #include "base/ossimFilename.h"
 
 #include "itkTimeProbe.h"
+#include "otbCurlHelper.h"
+
 
 namespace otb
 {
@@ -78,8 +80,6 @@ TileMapImageIO::TileMapImageIO()
 
   m_FileNameIsServerName = false;
 
-  // Initialize browser
-  m_Browser = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11";
   // Set maximum of connections to 10
   m_MaxConnect = 10;
 
@@ -152,17 +152,9 @@ void TileMapImageIO::Read(void* buffer)
   int nTilesX = (int) ceil(totSamples / 256.) + 1;
   int nTilesY = (int) ceil(totLines / 256.) + 1;
 
-  // Initialize curl multi handle
-  m_MultiHandle = curl_multi_init();
-
-  if (!m_MultiHandle)
-    {
-    itkExceptionMacro(<< "Tile Map IO : Curl mutli handle init error.");
-    }
 
   // Clear vectors
-  m_ListCurlHandles.clear();
-  m_ListFiles.clear();
+  m_ListFilename.clear();
   m_ListURLs.clear();
   m_ListTiles.clear();
 
@@ -182,17 +174,16 @@ void TileMapImageIO::Read(void* buffer)
       // Try to read tile from cache
       if (!this->CanReadFromCache(m_ListTiles.back().filename))
         {
-        // Generate curl handle for this tile
-        this->GenerateCURLHandle(m_ListTiles.back());
+	this->GenerateURL(m_ListTiles.back().x, m_ListTiles.back().y);
+	m_ListFilename.push_back(m_ListTiles.back().filename);
         }
       }
     }
 
-  // Fetch tiles from net
-  this->FetchTiles();
+  CurlHelper::Pointer curlHelper = CurlHelper::New();
+  curlHelper->RetrieveFileMulti(m_ListURLs, m_ListFilename, m_MaxConnect);
 
-  // Cleanup datas use to download tiles
-  this->Cleanup();
+  m_ListURLs.clear();
 
   // Generate buffer
   this->GenerateBuffer(p);
@@ -248,48 +239,6 @@ bool TileMapImageIO::CanReadFromCache(std::string filename)
   return lCanRead;
 }
 
-/*
- * This method generate curl handles and add to multi handle
- */
-void TileMapImageIO::GenerateCURLHandle(TileNameAndCoordType tileInfo)
-{
-  // Generate URL
-  this->GenerateURL(tileInfo.x, tileInfo.y);
-
-
-  // Create file
-  FILE* lOutputFile = fopen(tileInfo.filename.c_str(), "w");
-
-  if (lOutputFile == NULL)
-    {
-    itkExceptionMacro(<< "TileMap read : bad file name.");
-    }
-
-  // Add file to vector
-  m_ListFiles.push_back(lOutputFile);
-
-  // Initialize curl handle
-  CURL * lEasyHandle;
-  lEasyHandle = curl_easy_init();
-
-  if (!lEasyHandle)
-    {
-    itkExceptionMacro(<< "Tile Map IO : Curl easy handle init error.");
-    }
-
-
-  // Param easy handle
-  curl_easy_setopt(lEasyHandle, CURLOPT_USERAGENT, m_Browser.data());
-  curl_easy_setopt(lEasyHandle, CURLOPT_URL, m_ListURLs.back().data());
-  curl_easy_setopt(lEasyHandle, CURLOPT_WRITEDATA, m_ListFiles.back());
-
-  // Add easy handle to multi handle
-  curl_multi_add_handle(m_MultiHandle, lEasyHandle);
-
-  // Add hanle to vector
-  m_ListCurlHandles.push_back(lEasyHandle);
-}
-
 /*
  * This method generate URLs
  */
@@ -347,108 +296,6 @@ void TileMapImageIO::GenerateURL(double x, double y)
   m_ListURLs.push_back(urlStream.str());
 }
 
-/*
- * This method perform curl multi handle
- */
-void TileMapImageIO::FetchTiles()
-{
-  // Configure multi handle - set the maximum connections
-  curl_multi_setopt(m_MultiHandle, CURLMOPT_MAXCONNECTS, m_MaxConnect);
-  curl_multi_setopt(m_MultiHandle, CURLMOPT_PIPELINING, 0);
-
-  // Perform
-  int lStillRunning;
-
-  while (
-    CURLM_CALL_MULTI_PERFORM == curl_multi_perform(m_MultiHandle, &lStillRunning)
-    )
-    ;
-
-  // Now get that URL
-  while (lStillRunning)
-    {
-    struct timeval timeout;
-    int            rc; // Return code
-
-    fd_set fdread;
-    fd_set fdwrite;
-    fd_set fdexcep;
-    int    maxfd;
-
-    FD_ZERO(&fdread);
-    FD_ZERO(&fdwrite);
-    FD_ZERO(&fdexcep);
-
-    /* set a suitable timeout to play around with */
-    timeout.tv_sec = 0;
-    timeout.tv_usec = 1;
-
-    /* get file descriptors from the transfers */
-    curl_multi_fdset(m_MultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd);
-
-    rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
-
-    switch (rc)
-      {
-    case -1:
-      /* select error */
-      break;
-    case 0:
-    /* timeout */
-    default:
-      /* timeout or readable/writable sockets */
-      while (
-        CURLM_CALL_MULTI_PERFORM == curl_multi_perform(m_MultiHandle, &lStillRunning)
-        )
-        ;
-      break;
-      }
-    }
-
-  int      remaining_msgs = 1;
-  int      error = 0;
-  CURLMsg *msg;
-  while (remaining_msgs)
-    {
-    msg = curl_multi_info_read(m_MultiHandle, &remaining_msgs);
-    if (msg != NULL)
-      {
-      if (CURLE_OK != msg->data.result) error = 1;
-      }
-    }
-
-  if (error != 0)
-    {
-    itkExceptionMacro(<< "TileMapImageIO : Error occurs while perform Multi handle");
-    }
-}
-
-/*
- * This method cleanup datas
- */
-void TileMapImageIO::Cleanup()
-{
-  // Close files
-  for (unsigned int currentFile = 0; currentFile < m_ListFiles.size(); currentFile++)
-    {
-    fclose(m_ListFiles[currentFile]);
-    }
-  m_ListFiles.clear();
-
-  // Cleanup easy handles
-  for (unsigned int currentHandle = 0; currentHandle < m_ListCurlHandles.size(); currentHandle++)
-    {
-    curl_easy_cleanup(m_ListCurlHandles[currentHandle]);
-    }
-  m_ListCurlHandles.clear();
-
-  // Cleanup multi handle
-  curl_multi_cleanup(m_MultiHandle);
-
-  // Cleanup url vector
-  m_ListURLs.clear();
-}
-
 /*
  * This method generate the output buffer
  */
diff --git a/Code/IO/otbTileMapImageIO.h b/Code/IO/otbTileMapImageIO.h
index d8734e23053833959e3ad711aabe45baee4687bf..5dca3ed87228deb7c64a93263397d0cc77dddaa1 100644
--- a/Code/IO/otbTileMapImageIO.h
+++ b/Code/IO/otbTileMapImageIO.h
@@ -30,9 +30,6 @@
 #include "itkImageIOBase.h"
 #include "otbImageRegionTileMapSplitter.h"
 
-/* Curl Library*/
-#include <curl/curl.h>
-
 namespace otb
 {
 
@@ -190,19 +187,13 @@ private:
   /** CURL Multi */
   void GenerateTileInfo(double x, double y, int numTileX, int numTileY);
   bool CanReadFromCache(std::string filename);
-  void GenerateCURLHandle(TileNameAndCoordType tileInfo);
   void GenerateURL(double x, double y);
-  void FetchTiles();
-  void Cleanup();
   void GenerateBuffer(unsigned char * p);
   void ReadTile(std::string filename, void * buffer);
 
-  CURLM *                           m_MultiHandle;
-  std::vector<CURL *>               m_ListCurlHandles;
-  std::vector<FILE *>               m_ListFiles;
+  std::vector<std::string>          m_ListFilename;
   std::vector<std::string>          m_ListURLs;
   std::vector<TileNameAndCoordType> m_ListTiles;
-  std::string                       m_Browser;
   int                               m_MaxConnect;
 
   /** Byte per pixel pixel */
diff --git a/OTBConfig.cmake.in b/OTBConfig.cmake.in
index c37c000939598bf616f91d65070af61e58cebe39..4e3457b23d7db62afd28984584fd4cc6efe47089 100644
--- a/OTBConfig.cmake.in
+++ b/OTBConfig.cmake.in
@@ -109,6 +109,7 @@ SET(OTB_GL_USE_ACCEL "@OTB_GL_USE_ACCEL@")
 
 # Curl library
 SET(OTB_USE_CURL "@OTB_USE_CURL@")
+SET(OTB_CURL_MULTI_AVAILABLE "@OTB_CURL_MULTI_AVAILABLE@")
 
 #Developpers message
 SET(OTB_SHOW_ALL_MSG_DEBUG "@OTB_SHOW_ALL_MSG_DEBUG@")
diff --git a/UseOTB.cmake.in b/UseOTB.cmake.in
index e4e15b41c3e9d8990f5722862255e1b78ef6790b..7dac912f8aff53aec5060b35ceb86960d1ac25b9 100644
--- a/UseOTB.cmake.in
+++ b/UseOTB.cmake.in
@@ -132,3 +132,7 @@ ENDIF(OTB_USE_EXTERNAL_GDAL)
 IF(OTB_USE_CURL)
 ADD_DEFINITIONS(-DOTB_USE_CURL)
 ENDIF(OTB_USE_CURL)
+
+IF(OTB_CURL_MULTI_AVAILABLE)
+ADD_DEFINITIONS(-DOTB_CURL_MULTI_AVAILABLE)
+ENDIF(OTB_CURL_MULTI_AVAILABLE)