diff --git a/README.md b/README.md
index dc9420f8..316dcf0c 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,12 @@ The Arduino library is [under heavy development](https://github.com/googlesample
 - [FirebaseArduino API Reference](http://firebase-arduino.readthedocs.io/)
 
 ## Dependencies
-- FirebaseArduino now depends on [ArduinoJson library](https://github.com/bblanchon/ArduinoJson) instead of containing it's own version of it. Please either use Library Manager or download specific version of the library from github.
+
+FirebaseArduino depends on the following libraries:
+- [ArduinoJson library](https://github.com/bblanchon/ArduinoJson)
+- [ArduinoHttpClient library](https://github.com/arduino-libraries/ArduinoHttpClient/)
+
+Please either use Library Manager or download specific version of the library from github.
 
 ## Disclaimer
 
diff --git a/library.properties b/library.properties
index 37247e39..1574bac7 100644
--- a/library.properties
+++ b/library.properties
@@ -6,4 +6,4 @@ sentence=Library for communicating with Firebase.
 paragraph=This library simplifies the process of communicating with Firebase. It hides the complexity of authentication and json parsing.
 category=Communication
 url=https://github.com/googlesamples/firebase-arduino
-architectures=esp8266
+architectures=esp8266,esp32
diff --git a/src/FirebaseArduino.cpp b/src/FirebaseArduino.cpp
index 4ab93f0e..2558a66d 100644
--- a/src/FirebaseArduino.cpp
+++ b/src/FirebaseArduino.cpp
@@ -16,8 +16,26 @@
 
 #include "FirebaseArduino.h"
 
-// This is needed to compile std::string on esp8266.
-template class std::basic_string<char>;
+const char* kApplicationType = "application/json";
+const uint16_t kFirebasePort = 443;
+const int kStatusOK = 200;
+const int kStatusTemporaryRedirect = 307;
+
+String makeFirebaseURI(const String& path, const String& auth) {
+   String uri;
+   if (path[0] != '/') {
+     uri = "/";
+   }
+   uri += path;
+   uri += ".json";
+   if (auth.length() > 0) {
+     uri += "?auth=";
+     uri += auth;
+   }
+   return uri;
+}
+
+FirebaseArduino::FirebaseArduino(Client& client) : client_(client) {}
 
 void FirebaseArduino::begin(const String& host, const String& auth) {
   host_ = host.c_str();
@@ -26,17 +44,15 @@ void FirebaseArduino::begin(const String& host, const String& auth) {
 
 void FirebaseArduino::initStream() {
   if (stream_http_.get() == nullptr) {
-    stream_http_.reset(FirebaseHttpClient::create());
-    stream_http_->setReuseConnection(true);
-    stream_.reset(new FirebaseStream(stream_http_));
+    stream_http_.reset(new HttpClient(client_, host_, kFirebasePort));
+    stream_http_->connectionKeepAlive();
   }
 }
 
 void FirebaseArduino::initRequest() {
   if (req_http_.get() == nullptr) {
-    req_http_.reset(FirebaseHttpClient::create());
-    req_http_->setReuseConnection(true);
-    req_.reset(new FirebaseRequest(req_http_));
+    req_http_.reset(new HttpClient(client_, host_, kFirebasePort));
+    req_http_->connectionKeepAlive();
   }
 }
 
@@ -62,11 +78,20 @@ String FirebaseArduino::push(const String& path, const JsonVariant& value) {
   char * buf = new char[size];
   value.printTo(buf, size);
   initRequest();
-  int status = req_.get()->sendRequest(host_, auth_, "POST", path.c_str(), buf);
-  error_ = req_.get()->error();
-  const char* name = req_.get()->json()["name"].as<const char*>();
+  String uri = makeFirebaseURI(path, auth_);
+  int err = req_http_->post(uri.c_str(), kApplicationType, buf);
+  if (err != 0) {
+    error_ = FirebaseError(err, "HTTP request failed");
+    return "";
+  }
+  int statusCode = req_http_->responseStatusCode();
+  if (statusCode != kStatusOK) {
+    error_ = FirebaseError(statusCode, "PUT request failed");
+    return "";
+  }
   delete buf;
-  return name;
+  StaticJsonBuffer<FIREBASE_JSONBUFFER_SIZE> jsonBuffer;
+  return jsonBuffer.parseObject(req_http_->responseBody())["name"];
 }
 
 void FirebaseArduino::setInt(const String& path, int value) {
@@ -91,15 +116,34 @@ void FirebaseArduino::set(const String& path, const JsonVariant& value) {
   char* buf= new char[size];
   value.printTo(buf, size);
   initRequest();
-  req_.get()->sendRequest(host_, auth_, "PUT", path.c_str(), buf);
-  error_ = req_.get()->error();
+  String uri = makeFirebaseURI(path, auth_);
+  int err = req_http_->put(uri.c_str(), kApplicationType, buf);
+  if (err != 0) {
+    error_ = FirebaseError(err, "HTTP request failed");
+    return;
+  }
+  int statusCode = req_http_->responseStatusCode();
+  if (statusCode != kStatusOK) {
+    error_ = FirebaseError(statusCode, "POST request failed");
+    return;
+  }
+  req_http_->responseBody(); // consume body;
   delete buf;
 }
 
 void FirebaseArduino::getRequest(const String& path) {
   initRequest();
-  req_.get()->sendRequest(host_, auth_, "GET", path.c_str());
-  error_ = req_.get()->error();
+  String uri = makeFirebaseURI(path, auth_);
+  int err = req_http_->get(uri.c_str());
+  if (err != 0) {
+    error_ = FirebaseError(err, "HTTP request failed");
+    return;
+  }
+  int statusCode = req_http_->responseStatusCode();
+  if (statusCode != kStatusOK) {
+    error_ = FirebaseError(err, "GET request failed");
+    return;
+  }
 }
 
 FirebaseObject FirebaseArduino::get(const String& path) {
@@ -107,7 +151,7 @@ FirebaseObject FirebaseArduino::get(const String& path) {
   if (failed()) {
     return FirebaseObject{""};
   }
-  return FirebaseObject(req_.get()->response().c_str());
+  return FirebaseObject(req_http_->responseBody());
 }
 
 int FirebaseArduino::getInt(const String& path) {
@@ -115,7 +159,7 @@ int FirebaseArduino::getInt(const String& path) {
   if (failed()) {
     return 0;
   }
-  return FirebaseObject(req_.get()->response().c_str()).getInt();
+  return FirebaseObject(req_http_->responseBody()).getInt();
 }
 
 
@@ -124,7 +168,7 @@ float FirebaseArduino::getFloat(const String& path) {
   if (failed()) {
     return 0.0f;
   }
-  return FirebaseObject(req_.get()->response().c_str()).getFloat();
+  return FirebaseObject(req_http_->responseBody()).getFloat();
 }
 
 String FirebaseArduino::getString(const String& path) {
@@ -132,7 +176,7 @@ String FirebaseArduino::getString(const String& path) {
   if (failed()) {
     return "";
   }
-  return FirebaseObject(req_.get()->response().c_str()).getString();
+  return FirebaseObject(req_http_->responseBody()).getString();
 }
 
 bool FirebaseArduino::getBool(const String& path) {
@@ -140,40 +184,72 @@ bool FirebaseArduino::getBool(const String& path) {
   if (failed()) {
     return "";
   }
-  return FirebaseObject(req_.get()->response().c_str()).getBool();
+  return FirebaseObject(req_http_->responseBody()).getBool();
 }
+
 void FirebaseArduino::remove(const String& path) {
   initRequest();
-  req_.get()->sendRequest(host_, auth_, "DELETE", path.c_str());
-  error_ = req_.get()->error();
+  String uri = makeFirebaseURI(path, auth_);
+  int err = req_http_->del(uri.c_str());
+  if (err != 0) {
+    error_ = FirebaseError(err, "HTTP request failed");
+    return;
+  }
+  int statusCode = req_http_->responseStatusCode();
+  if (statusCode != kStatusOK) {
+    error_ = FirebaseError(statusCode, "PUT request failed");
+    return;
+  }
+  req_http_->responseBody(); // consume body;
 }
 
 void FirebaseArduino::stream(const String& path) {
   initStream();
-  stream_.get()->startStreaming(host_, auth_, path.c_str());
-  error_ = stream_.get()->error();
+  String uri = makeFirebaseURI(path, auth_);
+  stream_http_->beginRequest();
+  stream_http_->get(uri.c_str());
+  stream_http_->sendHeader("Accept", "text/event-stream");
+  stream_http_->endRequest();
+
+  int statusCode = stream_http_->responseStatusCode();
+  if (statusCode != kStatusOK) {
+    error_ = FirebaseError(statusCode, "STREAM request failed");
+    return;
+  }
+
+  if (statusCode == kStatusTemporaryRedirect) {
+    while(stream_http_->headerAvailable()) {
+      if (stream_http_->readHeaderName() == "Location") {
+        String location = stream_http_->readHeaderValue();
+        int hostnameStart = location.indexOf(':')+2;
+        int hostnameEnd = location.indexOf('/', hostnameStart);
+        String hostname = location.substring(hostnameStart, hostnameEnd);
+        String path = location.substring(hostnameEnd);
+        client_.stop();
+        stream_http_.reset(new HttpClient(client_, hostname, kFirebasePort));
+        stream_http_->connectionKeepAlive();
+        stream(path);
+        return;
+      }
+    }
+  }
 }
 
 bool FirebaseArduino::available() {
   if (stream_http_.get() == nullptr) {
-    return 0;
+    return false;
   }
-  auto client = stream_http_.get()->getStreamPtr();
-  return (client == nullptr) ? false : client->available();
+  return stream_http_->available();
 }
 
 FirebaseObject FirebaseArduino::readEvent() {
   if (stream_http_.get() == nullptr) {
     return FirebaseObject("");
   }
-  auto client = stream_http_.get()->getStreamPtr();
-  if (client == nullptr) {
-      return FirebaseObject("");
-  }
-  String type = client->readStringUntil('\n').substring(7);;
-  String event = client->readStringUntil('\n').substring(6);
-  client->readStringUntil('\n'); // consume separator
-  FirebaseObject obj = FirebaseObject(event.c_str());
+  String type = stream_http_->readStringUntil('\n').substring(7);;
+  String event = stream_http_->readStringUntil('\n').substring(6);
+  stream_http_->readStringUntil('\n'); // consume separator
+  FirebaseObject obj = FirebaseObject(event);
   obj.getJsonVariant().asObject()["type"] = type.c_str();
   return obj;
 }
@@ -190,4 +266,11 @@ const String& FirebaseArduino::error() {
   return error_.message().c_str();
 }
 
-FirebaseArduino Firebase;
+
+#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
+
+#include <WiFiClientSecure.h>
+WiFiClientSecure client;
+FirebaseArduino Firebase(client);
+
+#endif
diff --git a/src/FirebaseArduino.h b/src/FirebaseArduino.h
index e2f264e1..1db03d90 100644
--- a/src/FirebaseArduino.h
+++ b/src/FirebaseArduino.h
@@ -19,7 +19,9 @@
 
 #include <string>
 
-#include "Firebase.h"
+#include <ArduinoHttpClient.h>
+
+#include "FirebaseError.h"
 #include "FirebaseObject.h"
 
 /**
@@ -31,13 +33,15 @@
  */
 class FirebaseArduino {
  public:
+  FirebaseArduino(Client& client);
+
   /**
    * Must be called first. This initialize the client with the given
    * firebase host and credentials.
    * \param host Your firebase db host, usually X.firebaseio.com.
    * \param auth Optional credentials for the db, a secret or token.
    */
-  virtual void begin(const String& host, const String& auth = "");
+  void begin(const String& host, const String& auth = "");
 
   /**
    * Appends the integer value to the node at path.
@@ -77,7 +81,7 @@ class FirebaseArduino {
    * \param value String value that you wish to append to the node.
    * \return The unique key of the new child node.
    */
-  virtual String pushString(const String& path, const String& value);
+  String pushString(const String& path, const String& value);
 
   /**
    * Appends the JSON data to the node at path.
@@ -123,7 +127,7 @@ class FirebaseArduino {
    * \param path The path inside of your db to the node you wish to update.
    * \param value String value that you wish to write.
    */
-  virtual void setString(const String& path, const String& value);
+  void setString(const String& path, const String& value);
 
   /**
    * Writes the JSON data to the node located at path.
@@ -157,7 +161,7 @@ class FirebaseArduino {
    * \param path The path to the node you wish to retrieve.
    * \return The string value located at that path. Will only be populated if success() is true.
    */
-  virtual String getString(const String& path);
+  String getString(const String& path);
 
   /**
    * Gets the boolean value located at path.
@@ -181,7 +185,7 @@ class FirebaseArduino {
    * \param path The path to the node you wish to remove,
    * including all of its children.
    */
-  virtual void remove(const String& path);
+  void remove(const String& path);
 
   /**
    * Starts streaming any changes made to the node located at path, including
@@ -191,14 +195,14 @@ class FirebaseArduino {
    * monitoring available() and calling readEvent() to get new events.
    * \param path The path inside of your db to the node you wish to monitor.
    */
-  virtual void stream(const String& path);
+  void stream(const String& path);
 
   /**
    * Checks if there are new events available. This is only meaningful once
    * stream() has been called.
    * \return If a new event is ready.
    */
-  virtual bool available();
+  bool available();
 
   /**
    * Reads the next event in a stream. This is only meaningful once stream() has
@@ -206,7 +210,7 @@ class FirebaseArduino {
    * \return FirebaseObject will have ["type"] that describes the event type, ["path"]
    * that describes the effected path and ["data"] that was updated.
    */
-  virtual FirebaseObject readEvent();
+  FirebaseObject readEvent();
 
   /**
    * \return Whether the last command was successful.
@@ -221,15 +225,15 @@ class FirebaseArduino {
   /**
    * \return Error message from last command if failed() is true.
    */
-  virtual const String& error();
+  const String& error();
  private:
-  std::string host_;
-  std::string auth_;
+  Client& client_;
+
+  String host_;
+  String auth_;
   FirebaseError error_;
-  std::shared_ptr<FirebaseHttpClient> req_http_;
-  std::shared_ptr<FirebaseRequest> req_;
-  std::shared_ptr<FirebaseHttpClient> stream_http_;
-  std::shared_ptr<FirebaseStream> stream_;
+  std::shared_ptr<HttpClient> req_http_;
+  std::shared_ptr<HttpClient> stream_http_;
 
   void initStream();
   void initRequest();
diff --git a/src/FirebaseObject.cpp b/src/FirebaseObject.cpp
index 44fa5c37..35891dfe 100644
--- a/src/FirebaseObject.cpp
+++ b/src/FirebaseObject.cpp
@@ -26,6 +26,8 @@ FirebaseObject::FirebaseObject(const char* data) : data_{data} {
   // See: https://github.com/bblanchon/ArduinoJson/issues/279
 }
 
+FirebaseObject::FirebaseObject(const String& data) : FirebaseObject(data.c_str()) {}
+
 bool FirebaseObject::getBool(const String& path) const {
   JsonVariant variant = getJsonVariant(path);
   if (!variant.is<bool>()) {
diff --git a/src/FirebaseObject.h b/src/FirebaseObject.h
index 01caeb5c..611695f2 100644
--- a/src/FirebaseObject.h
+++ b/src/FirebaseObject.h
@@ -42,6 +42,12 @@ class FirebaseObject {
     */
     FirebaseObject(const char* data);
 
+    /**
+   * Construct from json.
+   * \param data JSON formatted string.
+    */
+    FirebaseObject(const String& data);
+
     /**
    * Return the value as a boolean.
    * \param optional path in the JSON object.