diff --git a/homeassistant/components/device_tracker/owntracks.py b/homeassistant/components/device_tracker/owntracks.py
index 1c773f97692914a39b43d27a9584755625c0d23d..07dc9f1ab5cbc172266fca3da041c958483f9d09 100644
--- a/homeassistant/components/device_tracker/owntracks.py
+++ b/homeassistant/components/device_tracker/owntracks.py
@@ -1,5 +1,5 @@
 """
-Support the OwnTracks platform.
+Device tracker platform that adds support for OwnTracks over MQTT.
 
 For more details about this platform, please refer to the documentation at
 https://home-assistant.io/components/device_tracker.owntracks/
@@ -64,13 +64,7 @@ def get_cipher():
 @asyncio.coroutine
 def async_setup_scanner(hass, config, async_see, discovery_info=None):
     """Set up an OwnTracks tracker."""
-    max_gps_accuracy = config.get(CONF_MAX_GPS_ACCURACY)
-    waypoint_import = config.get(CONF_WAYPOINT_IMPORT)
-    waypoint_whitelist = config.get(CONF_WAYPOINT_WHITELIST)
-    secret = config.get(CONF_SECRET)
-
-    context = OwnTracksContext(async_see, secret, max_gps_accuracy,
-                               waypoint_import, waypoint_whitelist)
+    context = context_from_config(async_see, config)
 
     @asyncio.coroutine
     def async_handle_mqtt_message(topic, payload, qos):
@@ -179,6 +173,17 @@ def _decrypt_payload(secret, topic, ciphertext):
         return None
 
 
+def context_from_config(async_see, config):
+    """Create an async context from Home Assistant config."""
+    max_gps_accuracy = config.get(CONF_MAX_GPS_ACCURACY)
+    waypoint_import = config.get(CONF_WAYPOINT_IMPORT)
+    waypoint_whitelist = config.get(CONF_WAYPOINT_WHITELIST)
+    secret = config.get(CONF_SECRET)
+
+    return OwnTracksContext(async_see, secret, max_gps_accuracy,
+                            waypoint_import, waypoint_whitelist)
+
+
 class OwnTracksContext:
     """Hold the current OwnTracks context."""
 
diff --git a/homeassistant/components/device_tracker/owntracks_http.py b/homeassistant/components/device_tracker/owntracks_http.py
new file mode 100644
index 0000000000000000000000000000000000000000..dcc3300cc12e7880095b3eb9954cf5f6e16163d9
--- /dev/null
+++ b/homeassistant/components/device_tracker/owntracks_http.py
@@ -0,0 +1,54 @@
+"""
+Device tracker platform that adds support for OwnTracks over HTTP.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/device_tracker.owntracks_http/
+"""
+import asyncio
+
+from aiohttp.web_exceptions import HTTPInternalServerError
+
+from homeassistant.components.http import HomeAssistantView
+
+# pylint: disable=unused-import
+from .owntracks import (  # NOQA
+    REQUIREMENTS, PLATFORM_SCHEMA, context_from_config, async_handle_message)
+
+
+DEPENDENCIES = ['http']
+
+
+@asyncio.coroutine
+def async_setup_scanner(hass, config, async_see, discovery_info=None):
+    """Set up an OwnTracks tracker."""
+    context = context_from_config(async_see, config)
+
+    hass.http.register_view(OwnTracksView(context))
+
+    return True
+
+
+class OwnTracksView(HomeAssistantView):
+    """View to handle OwnTracks HTTP requests."""
+
+    url = '/api/owntracks/{user}/{device}'
+    name = 'api:owntracks'
+
+    def __init__(self, context):
+        """Initialize OwnTracks URL endpoints."""
+        self.context = context
+
+    @asyncio.coroutine
+    def post(self, request, user, device):
+        """Handle an OwnTracks message."""
+        hass = request.app['hass']
+
+        message = yield from request.json()
+        message['topic'] = 'owntracks/{}/{}'.format(user, device)
+
+        try:
+            yield from async_handle_message(hass, self.context, message)
+            return self.json([])
+
+        except ValueError:
+            raise HTTPInternalServerError
diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py
index a00da9ee5b6d66edbfc2b0991e09379b94a6c034..4b971c883d3dd607ad66540628ac58e5fd853506 100644
--- a/homeassistant/components/http/auth.py
+++ b/homeassistant/components/http/auth.py
@@ -1,8 +1,11 @@
 """Authentication for HTTP component."""
 import asyncio
+import base64
 import hmac
 import logging
 
+from aiohttp import hdrs
+
 from homeassistant.const import HTTP_HEADER_HA_AUTH
 from .util import get_real_ip
 from .const import KEY_TRUSTED_NETWORKS, KEY_AUTHENTICATED
@@ -41,6 +44,10 @@ def auth_middleware(app, handler):
               validate_password(request, request.query[DATA_API_PASSWORD])):
             authenticated = True
 
+        elif (hdrs.AUTHORIZATION in request.headers and
+              validate_authorization_header(request)):
+            authenticated = True
+
         elif is_trusted_ip(request):
             authenticated = True
 
@@ -64,3 +71,22 @@ def validate_password(request, api_password):
     """Test if password is valid."""
     return hmac.compare_digest(
         api_password, request.app['hass'].http.api_password)
+
+
+def validate_authorization_header(request):
+    """Test an authorization header if valid password."""
+    if hdrs.AUTHORIZATION not in request.headers:
+        return False
+
+    auth_type, auth = request.headers.get(hdrs.AUTHORIZATION).split(' ', 1)
+
+    if auth_type != 'Basic':
+        return False
+
+    decoded = base64.b64decode(auth).decode('utf-8')
+    username, password = decoded.split(':', 1)
+
+    if username != 'homeassistant':
+        return False
+
+    return validate_password(request, password)
diff --git a/requirements_all.txt b/requirements_all.txt
index a5aab8adf0073199f9ab2b84c1af7870ac816eee..5f28a48ac8387027a8dfcb7ceebe1fb61fc13a02 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -373,6 +373,7 @@ jsonrpc-websocket==0.5
 keyring>=9.3,<10.0
 
 # homeassistant.components.device_tracker.owntracks
+# homeassistant.components.device_tracker.owntracks_http
 libnacl==1.5.2
 
 # homeassistant.components.dyson
diff --git a/tests/components/device_tracker/test_owntracks_http.py b/tests/components/device_tracker/test_owntracks_http.py
new file mode 100644
index 0000000000000000000000000000000000000000..be8bdd94ecc6b18c80bd62a4b26c62c55f3f8ae1
--- /dev/null
+++ b/tests/components/device_tracker/test_owntracks_http.py
@@ -0,0 +1,60 @@
+"""Test the owntracks_http platform."""
+import asyncio
+from unittest.mock import patch
+
+import pytest
+
+from homeassistant.setup import async_setup_component
+
+from tests.common import mock_coro, mock_component
+
+
+@pytest.fixture
+def mock_client(hass, test_client):
+    """Start the Hass HTTP component."""
+    mock_component(hass, 'group')
+    mock_component(hass, 'zone')
+    with patch('homeassistant.components.device_tracker.async_load_config',
+               return_value=mock_coro([])):
+        hass.loop.run_until_complete(
+            async_setup_component(hass, 'device_tracker', {
+                'device_tracker': {
+                    'platform': 'owntracks_http'
+                }
+            }))
+    return hass.loop.run_until_complete(test_client(hass.http.app))
+
+
+@pytest.fixture
+def mock_handle_message():
+    """Mock async_handle_message."""
+    with patch('homeassistant.components.device_tracker.'
+               'owntracks_http.async_handle_message') as mock:
+        mock.return_value = mock_coro(None)
+        yield mock
+
+
+@asyncio.coroutine
+def test_forward_message_correctly(mock_client, mock_handle_message):
+    """Test that we forward messages correctly to OwnTracks handle message."""
+    resp = yield from mock_client.post('/api/owntracks/user/device', json={
+        '_type': 'test'
+    })
+    assert resp.status == 200
+    assert len(mock_handle_message.mock_calls) == 1
+
+    data = mock_handle_message.mock_calls[0][1][2]
+    assert data == {
+        '_type': 'test',
+        'topic': 'owntracks/user/device'
+    }
+
+
+@asyncio.coroutine
+def test_handle_value_error(mock_client, mock_handle_message):
+    """Test that we handle errors from handle message correctly."""
+    mock_handle_message.side_effect = ValueError
+    resp = yield from mock_client.post('/api/owntracks/user/device', json={
+        '_type': 'test'
+    })
+    assert resp.status == 500
diff --git a/tests/components/http/test_auth.py b/tests/components/http/test_auth.py
index 5db42b01371e8c82c18a47005970d7cc0eaa6b62..ef9c63ad09e882053d79e6820ca59afa62d79304 100644
--- a/tests/components/http/test_auth.py
+++ b/tests/components/http/test_auth.py
@@ -4,6 +4,7 @@ import asyncio
 from ipaddress import ip_address, ip_network
 from unittest.mock import patch
 
+import aiohttp
 import pytest
 
 from homeassistant import const
@@ -149,3 +150,46 @@ def test_access_granted_with_trusted_ip(mock_api_client, caplog,
 
             assert resp.status == 200, \
                 '{} should be trusted'.format(remote_addr)
+
+
+@asyncio.coroutine
+def test_basic_auth_works(mock_api_client, caplog):
+    """Test access with basic authentication."""
+    req = yield from mock_api_client.get(
+        const.URL_API,
+        auth=aiohttp.BasicAuth('homeassistant', API_PASSWORD))
+
+    assert req.status == 200
+    assert const.URL_API in caplog.text
+
+
+@asyncio.coroutine
+def test_basic_auth_username_homeassistant(mock_api_client, caplog):
+    """Test access with basic auth requires username homeassistant."""
+    req = yield from mock_api_client.get(
+        const.URL_API,
+        auth=aiohttp.BasicAuth('wrong_username', API_PASSWORD))
+
+    assert req.status == 401
+
+
+@asyncio.coroutine
+def test_basic_auth_wrong_password(mock_api_client, caplog):
+    """Test access with basic auth not allowed with wrong password."""
+    req = yield from mock_api_client.get(
+        const.URL_API,
+        auth=aiohttp.BasicAuth('homeassistant', 'wrong password'))
+
+    assert req.status == 401
+
+
+@asyncio.coroutine
+def test_authorization_header_must_be_basic_type(mock_api_client, caplog):
+    """Test only basic authorization is allowed for auth header."""
+    req = yield from mock_api_client.get(
+        const.URL_API,
+        headers={
+            'authorization': 'NotBasic abcdefg'
+        })
+
+    assert req.status == 401