The Google Script will download your Fitbit data via the Fitbit API and insert it into a Google spreadsheet. The first row of the spreadsheet will be a header row containing data element names like steps walked, body fat, calories burned, etc. Subsequent rows will contain data, one day per row.
This is a Google Spreadsheet bound script so you need to create a sheet first and put this code inside the Script editor. Fitbit uses metric units (weight, distance) so you may wish to convert them as per your locale.
/* Original Fitbit script by loghound@gmail.com, Further modifications by Mark Leavitt, Christian Stade-Schuldt, Robert Furberg, Amit Agarwal (http to https) */ // Key of ScriptProperty for Fitbit consumer key. var CONSUMER_KEY_PROPERTY_NAME = "fitbitConsumerKey"; // Key of ScriptProperty for Fitbit consumer secret. var CONSUMER_SECRET_PROPERTY_NAME = "fitbitConsumerSecret"; // Default loggable resources (from Fitbit API docs). var LOGGABLES = ["activities/steps", "activities/distance", "activities/floors", "activities/elevation", "activities/calories", "activities/activityCalories", "activities/minutesSedentary", "activities/minutesLightlyActive", "activities/minutesFairlyActive", "activities/minutesVeryActive", "sleep/startTime", "sleep/timeInBed", "sleep/minutesAsleep", "sleep/awakeningsCount", "sleep/minutesAwake", "sleep/minutesToFallAsleep", "sleep/minutesAfterWakeup", "sleep/efficiency", "body/weight", "body/bmi", "body/fat"]; // function authorize() makes a call to the Fitbit API to fetch the user profile function authorize() { var oAuthConfig = UrlFetchApp.addOAuthService("fitbit"); oAuthConfig.setAccessTokenUrl("https://api.fitbit.com/oauth/access_token"); oAuthConfig.setRequestTokenUrl("https://api.fitbit.com/oauth/request_token"); oAuthConfig.setAuthorizationUrl("https://api.fitbit.com/oauth/authorize"); oAuthConfig.setConsumerKey(getConsumerKey()); oAuthConfig.setConsumerSecret(getConsumerSecret()); var options = { "oAuthServiceName": "fitbit", "oAuthUseToken": "always", }; // get the profile to force authentication Logger.log("Function authorize() is attempting a fetch..."); try { var result = UrlFetchApp.fetch("https://api.fitbit.com/1/user/-/profile.json", options); var o = Utilities.jsonParse(result.getContentText()); return o.user; } catch (exception) { Logger.log(exception); Browser.msgBox("Error attempting authorization"); return null; } } // function setup accepts and stores the Consumer Key, Consumer Secret, firstDate, and list of Data Elements function setup() { var doc = SpreadsheetApp.getActiveSpreadsheet(); var app = UiApp.createApplication().setTitle("Setup Fitbit Download"); app.setStyleAttribute("padding", "10px"); var consumerKeyLabel = app.createLabel("Fitbit OAuth Consumer Key:*"); var consumerKey = app.createTextBox(); consumerKey.setName("consumerKey"); consumerKey.setWidth("100%"); consumerKey.setText(getConsumerKey()); var consumerSecretLabel = app.createLabel("Fitbit OAuth Consumer Secret:*"); var consumerSecret = app.createTextBox(); consumerSecret.setName("consumerSecret"); consumerSecret.setWidth("100%"); consumerSecret.setText(getConsumerSecret()); var firstDate = app.createTextBox().setId("firstDate").setName("firstDate"); firstDate.setName("firstDate"); firstDate.setWidth("100%"); firstDate.setText(getFirstDate()); // add listbox to select data elements var loggables = app.createListBox(true).setId("loggables").setName( "loggables"); loggables.setVisibleItemCount(4); // add all possible elements (in array LOGGABLES) var logIndex = 0; for (var resource in LOGGABLES) { loggables.addItem(LOGGABLES[resource]); // check if this resource is in the getLoggables list if (getLoggables().indexOf(LOGGABLES[resource]) > -1) { // if so, pre-select it loggables.setItemSelected(logIndex, true); } logIndex++; } // create the save handler and button var saveHandler = app.createServerClickHandler("saveSetup"); var saveButton = app.createButton("Save Setup", saveHandler); // put the controls in a grid var listPanel = app.createGrid(6, 3); listPanel.setWidget(1, 0, consumerKeyLabel); listPanel.setWidget(1, 1, consumerKey); listPanel.setWidget(2, 0, consumerSecretLabel); listPanel.setWidget(2, 1, consumerSecret); listPanel.setWidget(3, 0, app.createLabel(" * (obtain these at dev.fitbit.com)")); listPanel.setWidget(4, 0, app.createLabel("Start Date for download (yyyy-mm-dd)")); listPanel.setWidget(4, 1, firstDate); listPanel.setWidget(5, 0, app.createLabel("Data Elements to download:")); listPanel.setWidget(5, 1, loggables); // Ensure that all controls in the grid are handled saveHandler.addCallbackElement(listPanel); // Build a FlowPanel, adding the grid and the save button var dialogPanel = app.createFlowPanel(); dialogPanel.add(listPanel); dialogPanel.add(saveButton); app.add(dialogPanel); doc.show(app); } // function sync() is called to download all desired data from Fitbit API to the spreadsheet function sync() { // if the user has never performed setup, do it now if (!isConfigured()) { setup(); return; } var user = authorize(); var doc = SpreadsheetApp.getActiveSpreadsheet(); doc.setFrozenRows(1); var options = { "oAuthServiceName": "fitbit", "oAuthUseToken": "always", "method": "GET" }; // prepare and format today's date, and a list of desired data elements var dateString = formatToday(); var activities = getLoggables(); // for each data element, fetch a list beginning from the firstDate, ending with today for (var activity in activities) { var currentActivity = activities[activity]; try { var result = UrlFetchApp.fetch("https://api.fitbit.com/1/user/-/" + currentActivity + "/date/" + getFirstDate() + "/" + dateString + ".json", options); } catch (exception) { Logger.log(exception); Browser.msgBox("Error downloading " + currentActivity); } var o = Utilities.jsonParse(result.getContentText()); // set title var titleCell = doc.getRange("a1"); titleCell.setValue("date"); var cell = doc.getRange('a2'); // fill the spreadsheet with the data var index = 0; for (var i in o) { // set title for this column var title = i.substring(i.lastIndexOf('-') + 1); titleCell.offset(0, 1 + activity * 1.0).setValue(title); var row = o[i]; for (var j in row) { var val = row[j]; cell.offset(index, 0).setValue(val["dateTime"]); // set the date index cell.offset(index, 1 + activity * 1.0).setValue(val["value"]); // set the value index index index++; } } } } function isConfigured() { return getConsumerKey() != "" && getConsumerSecret() != ""; } function setConsumerKey(key) { ScriptProperties.setProperty(CONSUMER_KEY_PROPERTY_NAME, key); } function getConsumerKey() { var key = ScriptProperties.getProperty(CONSUMER_KEY_PROPERTY_NAME); if (key == null) { key = ""; } return key; } function setLoggables(loggable) { ScriptProperties.setProperty("loggables", loggable); } function getLoggables() { var loggable = ScriptProperties.getProperty("loggables"); if (loggable == null) { loggable = LOGGABLES; } else { loggable = loggable.split(','); } return loggable; } function setFirstDate(firstDate) { ScriptProperties.setProperty("firstDate", firstDate); } function getFirstDate() { var firstDate = ScriptProperties.getProperty("firstDate"); if (firstDate == null) { firstDate = "2012-01-01"; } return firstDate; } function formatToday() { var todayDate = new Date; return todayDate.getFullYear() + '-' + ("00" + (todayDate.getMonth() + 1)).slice(-2) + '-' + ("00" + todayDate.getDate()).slice(-2); } function setConsumerSecret(secret) { ScriptProperties.setProperty(CONSUMER_SECRET_PROPERTY_NAME, secret); } function getConsumerSecret() { var secret = ScriptProperties.getProperty(CONSUMER_SECRET_PROPERTY_NAME); if (secret == null) { secret = ""; } return secret; } // function saveSetup saves the setup params from the UI function saveSetup(e) { setConsumerKey(e.parameter.consumerKey); setConsumerSecret(e.parameter.consumerSecret); setLoggables(e.parameter.loggables); setFirstDate(e.parameter.firstDate); var app = UiApp.getActiveApplication(); app.close(); return app; } // function onOpen is called when the spreadsheet is opened; adds the Fitbit menu function onOpen() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var menuEntries = [{ name: "Sync", functionName: "sync" }, { name: "Setup", functionName: "setup" }, { name: "Authorize", functionName: "authorize" }]; ss.addMenu("Fitbit", menuEntries); } // function onInstall is called when the script is installed (obsolete?) function onInstall() { onOpen(); }