Mar 162014

fitbit linux
I’ve recently received a fitbit flex as gift, and I love it, this personal device tracks steps, distance, and calories burned. At night, it tracks your sleep quality and wakes you silently in the morning. Just check out the lights to see how you stack up against your personal goal. Flex allows you to set a goal and uses LED lights to show how you’re stacking up. Each light represents 20% of your goal. You choose which one — steps, calories, or distance. It lights up like a scoreboard, challenging you to be more active day after day.

Flex automatically syncs your data to PCs and Macs with Fitbit’s wireless sync dongle (included), many iOS devices and select Android phones without plugging in or pushing buttons. Now all this sound fantastic and really funny if you like to take your stats and see nice graphs, but there is a small (big) problem about fitbit, it doesn’t support officially Linux.

Sure, you can use a compatible smartphone, but in general I like to use the idea of using my Linux computers for anything and with some research and some tests I’ve been able to sync successfully my flex with my Linux Mint 16.

From Fitbit one and Debian:

First, I’ll start with some technical information about the fitbit. The new fitbit systems use Bluetooth 4.0 LE to sync, rather than the proprietary ANT protocol. This is both good and bad for developers. The Bluetooth protocol is open enough to develop for, but there is still an issue of how to communicate with the fitbit tracker. Luckily for us, there are developers who have been working on ways to do this.

The oldest implementation of fitbit sync was with libfitbit — this used the ANT protocol to sync the trackers. This evolved and evolved until a kind person named Benoît Allard created a python script called galileo. This is the script we are going to be using to sync the tracker. An interesting thing about fitbit, is that the server parses the device ID and links the transmitted data to the appropriate accounts, rather than a client-side application being linked to a certain account. It makes the syncing a little bit easier.

Galileo is a Python utility to securely synchronize a Fitbit device with the Fitbit web service. It allows you to browse your data on their website, and their apps.

All Bluetooth-based trackers are supported. Those are:

  • Fitbit One
  • Fitbit Zip
  • Fitbit Flex
  • Probably Fitbit Force

note: The Fitbit Ultra tracker is **not supported** as it communicates using the ANT protocol. To synchronize use libfitbit.

Main features of Galileo are:

  • Synchronize your fitbit tracker with the fitbit server using the provided dongle.
  • Securely communicate (using HTTPS) with the fitbit server.
  • Save all your dumps locally for possible later analyse.

Dan, the author of the article successfully installed the stable release of Galileo on a Debian 7 and everything worked out of the box for him, I did not have the same luck on my Mint 16, so probably most of the Ubuntu users will have my same problems, but with some tweak I managed to make it work, here is how.

Disclaimer: Galileo it’s still in its early phases and it’s available only on the command line, so don’t expect to have a graphical application similar to the one you find in Windows, so to use it you must work on the terminal, the good news it’s that it’s not so hard to make it work and probably in the future some graphical application based on it will be available for all.

Install the requisite libraries

Galileo is wrote in python so we need the usb libraries for python for Debian based distribution you can use this command:

sudo apt-get install python-usb python-requests

Galileo require pyusb at least a 1.0 version, 0.4 and earlier are not compatible so I followed Dan suggestion and I updated manually the python-usb library with his instructions:

Download the pyusb script from the zip file here.

Unzip the folder into a convenient location.

Go to the new directory in a terminal as root and run the following command:

python install

Now you have the prerequisites ready.

Install Galileo, method 1

As first method I suggest to try to install Galileo in the “standard” way, this seem to work for some distributions (Debian and Arch), to do this open a terminal and type:

sudo pip install galileo

You should get an output similar to this one:

$ sudo pip install galileo
Downloading/unpacking galileo
  Downloading galileo-0.3.1.tar.gz
  Running egg_info for package galileo
Requirement already satisfied (use --upgrade to upgrade): requests in /usr/lib/python2.7/dist-packages (from galileo)
Requirement already satisfied (use --upgrade to upgrade): pyusb in /usr/local/lib/python2.7/dist-packages (from galileo)
Installing collected packages: galileo
  Running install for galileo
    Installing galileo script to /usr/local/bin
Successfully installed galileo
Cleaning up...

Now you can test this version of galileo with the command:

sudo galileo

If everything works you should something like:

1 trackers found, 0 skipped, 1 successfully synchronized

And you can skip to section”How to run Galileo as non-root user”, in my case I got this error:

$ sudo galileo
Traceback (most recent call last):
  File "/usr/local/bin/galileo", line 9, in 
    load_entry_point('galileo==0.3.1', 'console_scripts', 'galileo')()
  File "/usr/local/lib/python2.7/dist-packages/", line 564, in main
    total, success, skipped = syncAllTrackers(cmdlineargs.force, cmdlineargs.dump)
  File "/usr/local/lib/python2.7/dist-packages/", line 423, in syncAllTrackers
  File "/usr/local/lib/python2.7/dist-packages/", line 203, in disconnect
    self.dongle.ctrl_write([2, 2])
  File "/usr/local/lib/python2.7/dist-packages/", line 150, in ctrl_write
    l =, data, self.CtrlIF.bInterfaceNumber, timeout=timeout)
TypeError: write() got multiple values for keyword argument 'timeout'

so I moved to method 2

Install Galileo, method 2

I downloaded the zip of the latest version from the project page and unzipped it.
Now in the new directory you’ll find the run command, that in this version replaces the command galileo.

To test it move in the new directory and give the command:

sudo ./run

Once again, if you see a successful output you are done and can move to next section, in my case I still got an error:

$ sudo ./run
No handlers could be found for logger "galileo.config"
# A serious error happened, which is probably due to a
# programming error. Please open a new issue with the following
# information on the galileo bug tracker:
# ./run: 0.4dev
# Python: 2.7.5+ (default, Feb 27 2014, 19:37:08) [GCC 4.8.1]
# Platform: Linux mint-desktop 3.11.0-12-generic #19-Ubuntu SMP Wed Oct 9 16:20:46 UTC 2013 x86_64 x86_64
# pyusb: 1.0.0b2
# requests: 1.2.3
# yaml: own version
Traceback (most recent call last):
  File "./run", line 5, in 
  File "/home/linuxaria/Downloads/benallard-galileo-540c1f6d394a/galileo/", line 239, in main
  File "/home/linuxaria/Downloads/benallard-galileo-540c1f6d394a/galileo/", line 174, in sync
    total, success, skipped = syncAllTrackers(config)
  File "/home/linuxaria/Downloads/benallard-galileo-540c1f6d394a/galileo/", line 37, in syncAllTrackers
  File "/home/linuxaria/Downloads/benallard-galileo-540c1f6d394a/galileo/", line 36, in disconnect
    self.dongle.ctrl_write([2, 2])
  File "/home/linuxaria/Downloads/benallard-galileo-540c1f6d394a/galileo/", line 115, in ctrl_write
    l =, data, self.CtrlIF.bInterfaceNumber, timeout)
TypeError: write() takes at most 4 arguments (5 given)

Looking in the issue tracker of Galileo I found this entry:

Benoît Allard

This is a duplicate of issue #36 and #27. Please use a tagged release of pyusb, or remove the third parameter in the calls to write and read in galileo/

I’m not a python programmer, but I tried to follow that instruction and so I removed the third parameter in the file galileo/, in short remove the parameter self.CtrlIF.bInterfaceNumber in the lines : 115, 122, 136 and 144 (the line number could change in future releases).

This is a diff from the original file and the one I’ve changed:

< l =, data, self.CtrlIF.bInterfaceNumber, timeout) --- >         l =, data=data, timeout=timeout)
< data =, length, self.CtrlIF.bInterfaceNumber, --- >             data =, length,
< l =, msg.asList(), self.DataIF.bInterfaceNumber, --- >         l =, msg.asList(), 
< data =, 32, self.DataIF.bInterfaceNumber, --- >             data =, 32,

And with this change now it finally works on my Mint 16 !!

$ ./ sudo run -v
2014-03-16 22:38:11,302:INFO: Running in mode: sync
2014-03-16 22:38:11,314:INFO: Disconnecting from any connected trackers
2014-03-16 22:38:13,328:INFO: Discovering trackers to synchronize
2014-03-16 22:38:17,340:INFO: 1 trackers discovered
2014-03-16 22:38:17,340:INFO: Attempting to synchronize tracker EDB71B44D7D7
2014-03-16 22:38:17,353:INFO: Starting new HTTPS connection (1):
2014-03-16 22:38:26,911:INFO: Getting data from tracker
2014-03-16 22:38:27,819:INFO: Sending tracker data to Fitbit
2014-03-16 22:38:27,821:INFO: Starting new HTTPS connection (1):
2014-03-16 22:38:29,566:INFO: Successfully sent tracker data to Fitbit
2014-03-16 22:38:29,567:INFO: Passing Fitbit response to tracker
1 trackers found, 0 skipped, 1 successfully synchronized

Useful options in Galileo

I’m using version 0.4dev, in version 0.3 you could not have all these options:

logging Verbosity:
-v, –verbose display synchronization progress
-d, –debug show internal activity (implies verbose)
-q, –quiet only show errors and summary (default)

whether or not to synchronize even if tracker reports a recent sync (< 15 minutes)

–no-force DEFAULT

So by default if you use the run command 2 times on the second it will NOT send the data to and you’ll see a skip message:

$ sudo ./run  -v
No handlers could be found for logger "galileo.config"
2014-03-16 22:39:51,946:INFO: Disconnecting from any connected trackers
2014-03-16 22:39:53,959:INFO: Discovering trackers to synchronize
2014-03-16 22:39:57,971:INFO: 1 trackers discovered
2014-03-16 22:39:57,972:INFO: Tracker EDB71B44D7D7 was recently synchronized; skipping for now
2014-03-16 22:39:57,972:INFO: Tracker EDB71B44D7D7 is to be skipped due to configuration; skipping
1 trackers found, 1 skipped, 0 successfully synchronized

whether or not to enable saving of the megadump to a file


The dumps are located by default in the directory ~/.galileo/YOURTRACKERID/ and are binary files, if you don’t have plan to use them you can use the option –no-dump.

How to run Galileo as non-root user

Running galileo requires sudo, but you can get around that limitation by adding a simple udev rule. Create and add the following to /etc/udev/rules.d/99-fitbit.rules

SUBSYSTEM=="usb", ATTR{idVendor}=="2687", ATTR{idProduct}=="fb01", SYMLINK+="fitbit", MODE="0666"

Don’t forget to:

restart the udev service:

sudo service udev restart

unplug and re-insert the dongle to activate the new rule.


As you can see the project it’s still new and need some tweaking to work, but has a lot of potentials and useful options.
Once it works on your PC you can setup a cron every 30 minutes or more to sync your data with the website, or you can run it as daemon (only on version 0.4 or later) and have all your stats updated from your GNU/Linux box.

Now you can also invite me to be your friend on, my email there it’s [email protected]

Happy training to all GNU/Linux users !!

Popular Posts:

flattr this!

  17 Responses to “How to sync your Fitbit under Linux”

  1. Galileo is great! One less reason to keep Windows around in a VM.

    After I downloaded galileo, it installed on Fedora 19 without a hitch. I used the following two commands

    yum -y install python-pip pyusb python-requests
    pip install galileo

    Looking forward to seeing the evolution of this product.

  2. Excellent, thank you for this guide.
    I only have one issue left now and thats running it as non sudo
    Followed your guide and created the udev rule, restarted udev etc and it works, but only once , after that it will only work using sudo.
    Seems to work if i pull dongle out and put it back in but will have to check that again in a bit.

    Again thank you for your superb guide

  3. I’ve made it easier for Ubuntu users and packaged galileo in a PPA, so now all you need to do is `sudo add-apt-repository ppa:cwayne18 && sudo apt-get update && sudo apt-get install galileo` and then reboot, and syncing will take place automatically

  4. Followed Chris’s instructions for Ubuntu dated 04/26/2014 above on 14.04 amd64 and was advised “Unable to locate package galileo.”

  5. The install mostly worked for Ubuntu Precise, except for galileo itself.
    ]$ sudo apt-get install galileo
    Reading package lists… Done
    Building dependency tree
    Reading state information… Done
    E: Unable to locate package galileo

    ]$ sudo apt-get install fitbit-steps-indicator
    Reading package lists… Done
    Building dependency tree
    Reading state information… Done
    The following packages were automatically installed and are no longer required:
    libts-0.0-0:i386 twolame linux-headers-3.2.0-29
    linux-headers-3.2.0-29-generic libaften0 nvidia-settings-304 mjpegtools
    Use ‘apt-get autoremove’ to remove them.
    The following NEW packages will be installed:
    0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
    Need to get 8,070 B of archives.
    After this operation, 60.4 kB of additional disk space will be used.
    Get:1 precise/main fitbit-steps-indicator amd64 0.2~precise1 [8,070 B]
    Fetched 8,070 B in 0s (25.4 kB/s)
    Selecting previously unselected package fitbit-steps-indicator.
    (Reading database … 839219 files and directories currently installed.)
    Unpacking fitbit-steps-indicator (from …/fitbit-steps-indicator_0.2~precise1_amd64.deb) …
    Setting up fitbit-steps-indicator (0.2~precise1) …

  6. This is fantastic. I was wanting to get this going on Raspberry Pi.
    Worked on it with both Raspbian and Pidora. Pidora required less work.

    be sure to apt-get update and apt-get dist-upgrade and apt-get install python-requests (as mentioned above)
    usbhid.quirks=0x2687:0xfb01:0x0004 added to /boot/cmdline.txt (to keep usbhid from taking over the dongle)
    manual upgrade of libusb (1.0.19 I think,, download, unpack, ./configure, make and make install — configure required more packages but I don’t recall which) in order for 1.0.0b2 of pyusb and 0.5dev (maybe 0.4 too) of galileo to work.

    Pidora needed pyusb updated only.

    galileo needed adjustments to the write and read params in similarly as mentioned above.

    Also had trouble running in daemon mode (my preference). Kept getting Resource busy on the second run. Finally figured out how to fix that (after many hours trying to understand the code). In in class USBDevice change:

    def __del__(self):


    def __del__(self):

    This made it work nicely.

    Now just need to add wifi dongle and connect to local wireless, pick a nice central location and power it up and let it go.

    • Your fix has been integrated into galileo. Thank you very much !

      Next time that you spend some time fixing an open-source project, consider proposing the change to the original project so that more people can benefit from it ! I would probably have never seen it on my own !

  7. I have the same unable to locate package issue:
    E: unable to locate package galileo

    Ubuntu version is 12.04

  8. Is this known to work with Fitbit Charge?

  9. I had to register my FitBit Charge on a Windows 7 machine but it appears I am able to sync with Fitbit using galileo.

    Is there a way to register a FitBit using galileo?

  10. Hello,
    Could someone help me? It looks that I successfuly install galileo but it failed to discover tracker. I have this error:
    galileo -d
    2015-01-09 20:50:08,810:DEBUG: Configuration: {‘httpsOnly': True, ‘logLevel': 10, ‘doUpload': True, ‘keepDumps': True, ‘includeTrackers': None, ‘forceSync': False, ‘rcConfigName': None, ‘dumpDir': ‘~/.galileo’, ‘daemonPeriod': 15000, ‘excludeTrackers': set([]), ‘mode': ‘sync’}
    2015-01-09 20:50:08,810:DEBUG: galileo initialising
    2015-01-09 20:50:08,829:INFO: Disconnecting from any connected trackers
    2015-01-09 20:50:08,830:DEBUG: –> 02 – 2
    2015-01-09 20:50:08,830:DEBUG: Switching to a newer pyusb compatibility mode
    2015-01-09 20:50:08,836:DEBUG: <– CancelDiscovery
    2015-01-09 20:50:08,840:DEBUG: <– TerminateLink
    2015-01-09 20:50:08,842:DEBUG: <– 02 ( 00 ) – 3
    # A serious error happened, which is probably due to a
    # programming error. Please open a new issue with the following
    # information on the galileo bug tracker:
    # /usr/local/bin/galileo: 0.4.2
    # Python: 2.7.3 (default, Dec 18 2014, 19:03:52) [GCC 4.6.3]
    # Platform: Linux eliya-LifeBook-A6025 3.2.0-74-generic #109-Ubuntu SMP Tue Dec 9 16:47:54 UTC 2014 i686 i686
    # pyusb: 1.0.0rc1
    # requests: 0.8.2
    # yaml: 3.10 (with libyaml)
    Traceback (most recent call last):
    File "/usr/local/bin/galileo", line 9, in
    load_entry_point(‘galileo==0.4.2′, ‘console_scripts’, ‘galileo’)()
    File “/usr/local/lib/python2.7/dist-packages/galileo/”, line 267, in main
    File “/usr/local/lib/python2.7/dist-packages/galileo/”, line 197, in sync
    for tracker in syncAllTrackers(config):
    File “/usr/local/lib/python2.7/dist-packages/galileo/”, line 38, in syncAllTrackers
    File “/usr/local/lib/python2.7/dist-packages/galileo/”, line 48, in disconnect
    File “/usr/local/lib/python2.7/dist-packages/galileo/”, line 212, in ctrl_read
    data =, length, timeout)
    File “/usr/local/lib/python2.7/dist-packages/galileo/”, line 191, in read
    File “/usr/local/lib/python2.7/dist-packages/usb/”, line 925, in read
    File “/usr/local/lib/python2.7/dist-packages/usb/backend/”, line 835, in intr_read
    File “/usr/local/lib/python2.7/dist-packages/usb/backend/”, line 920, in __read
    File “/usr/local/lib/python2.7/dist-packages/usb/backend/”, line 588, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
    usb.core.USBError: [Errno 19] No such device (it may have been disconnected)

  11. Well … it looks that it works with Charge as well.
    Initially I reported that it does not work but after I restarted Charge Fitbit and ran command it discovered and synced.
    $ galileo -v
    2015-01-09 23:14:42,744:INFO: Disconnecting from any connected trackers
    2015-01-09 23:14:44,758:INFO: Discovering trackers to synchronize
    2015-01-09 23:14:48,768:INFO: 1 trackers discovered
    2015-01-09 23:14:48,768:INFO: Tracker A2F88DECDDE5 was recently synchronized; skipping for now
    2015-01-09 23:14:48,769:INFO: Tracker A2F88DECDDE5 skipped due to configuration
    Tracker: A2F88DECDDE5: Skipped because recently synchronised

  12. On Linux Mint 17 and
    FitBit one
    I may be out of my depth here but….
    I used you tute using method 1 and got to “:-

    val-GA-78LMT-S2P pyusb-master # apt-get install galileo
    Reading package lists… Done
    Building dependency tree
    Reading state information… Done
    galileo is already the newest version.
    0 to upgrade, 0 to newly install, 0 to remove and 33 not to upgrade.

    then i ran galileo :-

    val-GA-78LMT-S2P pyusb-master # galileo
    # A serious error happened, which is probably due to a
    # programming error. Please open a new issue with the following
    # information on the galileo bug tracker:
    # /usr/bin/galileo: 0.5dev
    # Python: 2.7.6 (default, Mar 22 2014, 22:59:38) [GCC 4.8.2]
    # Platform: Linux val-GA-78LMT-S2P 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:31:42 UTC 2014 i686 athlon
    # pyusb: 1.0.0rc1
    # requests: 2.2.1
    # yaml: own version
    # Last communications:
    Traceback (most recent call last):
    File “/usr/bin/galileo”, line 9, in
    load_entry_point(‘galileo==0.5dev’, ‘console_scripts’, ‘galileo’)()
    File “/usr/lib/python2.7/dist-packages/galileo/”, line 284, in main
    File “/usr/lib/python2.7/dist-packages/galileo/”, line 193, in sync
    for tracker in syncAllTrackers(config):
    File “/usr/lib/python2.7/dist-packages/galileo/”, line 31, in syncAllTrackers
    if not dongle.setup():
    File “/usr/lib/python2.7/dist-packages/galileo/”, line 225, in setup
    File “/usr/local/lib/python2.7/dist-packages/usb/”, line 811, in set_configuration
    self._ctx.managed_set_configuration(self, configuration)
    File “/usr/local/lib/python2.7/dist-packages/usb/”, line 129, in managed_set_configuration
    self.backend.set_configuration(self.handle, cfg.bConfigurationValue)
    File “/usr/local/lib/python2.7/dist-packages/usb/backend/”, line 781, in set_configuration
    _check(self.lib.libusb_set_configuration(dev_handle.handle, config_value))
    File “/usr/local/lib/python2.7/dist-packages/usb/backend/”, line 588, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
    usb.core.USBError: [Errno 16] Resource busy

    Is there enough info here to make a comment on what’s wrong here ?

  13. For what it’s worth . . . Current distro (*NOT* package!) as of 3/8/2015, and Slackware 14.1 . . . Added the two python dependencies, placed the udev rule, typed “run” and watched it work . . .

    Not sure why they call that the “hard way” . . . to me, packages where you don’t get to see what is going on is the really hard way . . . But in any case, this worked flawlessly right out of the box!

    – Tim

 Leave a Reply




You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>