diff --git a/.coveragerc b/.coveragerc
index c8958d98178dab3e4d425a57840b2b00a547108e..c51f6bc37cbca0b077b8b416fecb776b57c5b4c0 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -397,6 +397,7 @@ omit =
     homeassistant/components/device_tracker/bt_home_hub_5.py
     homeassistant/components/device_tracker/cisco_ios.py
     homeassistant/components/device_tracker/ddwrt.py
+    homeassistant/components/device_tracker/freebox.py
     homeassistant/components/device_tracker/fritz.py
     homeassistant/components/device_tracker/google_maps.py
     homeassistant/components/device_tracker/gpslogger.py
diff --git a/homeassistant/components/device_tracker/freebox.py b/homeassistant/components/device_tracker/freebox.py
new file mode 100644
index 0000000000000000000000000000000000000000..67957ca99b9f6889ebf329f06c6f3524a94a13a2
--- /dev/null
+++ b/homeassistant/components/device_tracker/freebox.py
@@ -0,0 +1,120 @@
+"""
+Support for device tracking through Freebox routers.
+
+This tracker keeps track of the devices connected to the configured Freebox.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/device_tracker.freebox/
+"""
+import asyncio
+import copy
+import logging
+import socket
+from collections import namedtuple
+from datetime import timedelta
+
+import voluptuous as vol
+
+import homeassistant.helpers.config_validation as cv
+from homeassistant.helpers.event import async_track_time_interval
+from homeassistant.components.device_tracker import (
+    PLATFORM_SCHEMA, CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
+from homeassistant.const import (
+    CONF_HOST, CONF_PORT)
+
+REQUIREMENTS = ['aiofreepybox==0.0.3']
+
+_LOGGER = logging.getLogger(__name__)
+
+FREEBOX_CONFIG_FILE = 'freebox.conf'
+
+PLATFORM_SCHEMA = vol.All(
+    PLATFORM_SCHEMA.extend({
+        vol.Required(CONF_HOST): cv.string,
+        vol.Required(CONF_PORT): cv.port
+    }))
+
+MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
+
+
+async def async_setup_scanner(hass, config, async_see, discovery_info=None):
+    """Set up the Freebox device tracker and start the polling."""
+    freebox_config = copy.deepcopy(config)
+    if discovery_info is not None:
+        freebox_config[CONF_HOST] = discovery_info['properties']['api_domain']
+        freebox_config[CONF_PORT] = discovery_info['properties']['https_port']
+        _LOGGER.info("Discovered Freebox server: %s:%s",
+                     freebox_config[CONF_HOST], freebox_config[CONF_PORT])
+
+    scanner = FreeboxDeviceScanner(hass, freebox_config, async_see)
+    interval = freebox_config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
+    await scanner.async_start(hass, interval)
+    return True
+
+
+Device = namedtuple('Device', ['id', 'name', 'ip'])
+
+
+def _build_device(device_dict):
+    return Device(
+        device_dict['l2ident']['id'],
+        device_dict['primary_name'],
+        device_dict['l3connectivities'][0]['addr'])
+
+
+class FreeboxDeviceScanner(object):
+    """This class scans for devices connected to the Freebox."""
+
+    def __init__(self, hass, config, async_see):
+        """Initialize the scanner."""
+        from aiofreepybox import Freepybox
+
+        self.host = config[CONF_HOST]
+        self.port = config[CONF_PORT]
+        self.token_file = hass.config.path(FREEBOX_CONFIG_FILE)
+        self.async_see = async_see
+
+        # Hardcode the app description to avoid invalidating the authentication
+        # file at each new version.
+        # The version can be changed if we want the user to re-authorize HASS
+        # on her Freebox.
+        app_desc = {
+            'app_id': 'hass',
+            'app_name': 'Home Assistant',
+            'app_version': '0.65',
+            'device_name': socket.gethostname()
+        }
+
+        api_version = 'v1'  # Use the lowest working version.
+        self.fbx = Freepybox(
+            app_desc=app_desc,
+            token_file=self.token_file,
+            api_version=api_version)
+
+    async def async_start(self, hass, interval):
+        """Perform a first update and start polling at the given interval."""
+        await self.async_update_info()
+        interval = max(interval, MIN_TIME_BETWEEN_SCANS)
+        async_track_time_interval(hass, self.async_update_info, interval)
+
+    async def async_update_info(self, now=None):
+        """Check the Freebox for devices."""
+        from aiofreepybox.exceptions import HttpRequestError
+
+        _LOGGER.info('Scanning devices')
+
+        await self.fbx.open(self.host, self.port)
+        try:
+            hosts = await self.fbx.lan.get_hosts_list()
+        except HttpRequestError:
+            _LOGGER.exception('Failed to scan devices')
+        else:
+            active_devices = [_build_device(device)
+                              for device in hosts
+                              if device['active']]
+
+            if active_devices:
+                await asyncio.wait([self.async_see(mac=d.id, host_name=d.name)
+                                    for d in active_devices])
+
+        await self.fbx.close()
diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py
index 69447b81cd427ec8fccca4002bd2de4a42173002..00d4291539b9367663bc943a868e696d20ebefbe 100644
--- a/homeassistant/components/discovery.py
+++ b/homeassistant/components/discovery.py
@@ -84,6 +84,7 @@ SERVICE_HANDLERS = {
     'kodi': ('media_player', 'kodi'),
     'volumio': ('media_player', 'volumio'),
     'nanoleaf_aurora': ('light', 'nanoleaf_aurora'),
+    'freebox': ('device_tracker', 'freebox'),
 }
 
 OPTIONAL_SERVICE_HANDLERS = {
diff --git a/requirements_all.txt b/requirements_all.txt
index 24c2df99ebb7f9a3950b10c91a9e11339cb24da9..8673f4aa22f504ca20008efca8edc2cba90384b2 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -81,6 +81,9 @@ aioautomatic==0.6.5
 # homeassistant.components.sensor.dnsip
 aiodns==1.1.1
 
+# homeassistant.components.device_tracker.freebox
+aiofreepybox==0.0.3
+
 # homeassistant.components.emulated_hue
 # homeassistant.components.http
 aiohttp_cors==0.7.0