I have a form / survey created for Survey123. It has been published and I can access the data which has been captured through the ArcGIS Online Portal.

I would like to read the attribute information from this form in Excel. Similarly as I have connections to my SQL Databases and I can read the attribute information stored in the databases connected to my Collector for ArcGIS maps.

I know how to download the CSV / SHP / FGDB information, but I would like to connect to this information without the need to have a user logon to the AGOL and download it. Some users will not have ArcGIS Installed on their machines, so using Python is an option, but I cannot use arcpy.

Is there a workflow that will allow me to have a live connection between Excel and the attribute information stored in my Survey123 Form?


2 Answers 2


You can configure your survey123 form with a webhook, so everytime data is submitted, a new record is added into an xls file hosted in Microsoft 365 or in a Google Spreadsheet.

In this way, you have a spreadsheet showing live data from Survey123 and people dont need anything extra to look at the data.

You can learn more about webhooks in survey123 here


And here:


Microsoft Flow, Zapier, Integromat... are all great options with connectors that let you work with spreadsheets.


You can connect to AGOL from Excel using Power Query. Under the Data tab, click Get Data then choose Launch Power Query Editor On the far right, click New Source and choose Other Source then choose Blank Query Now click Advanced Editor

If your Survey is not public then you will first need to get an authorization token. Paste the following M code and replace with your credentials.

    GetJson = Web.Contents("https://www.arcgis.com/sharing/rest/generateToken/", [Headers=[Accept="application/json", #"Content-Type"="application/x-www-form-urlencoded;charset=UTF-8"], Query=[referer = "https://www.arcgis.com", f = "pjson"], Content=Text.ToBinary("username=####YOUR USENAME###&password=###YOUR PASSWORD###")]),
    FormatAsJson = Json.Document(GetJson),
    token = FormatAsJson[token],

Next you will use this token to query the hosted feature layer from your survey and convert it into a table. The Feature Service URL for your Hosted Feature Layer is found in the bottom right of the Overview Page. EG for Cellular Towers in the United States the Overview page is: https://www.arcgis.com/home/item.html?id=15dabb4108254481b591018be2598f3c#overview and the Service URL in the bottom right is: https://services1.arcgis.com/Hp6G80Pky0om7QvQ/arcgis/rest/services/Cellular_Towers/FeatureServer/0 There's even a copy button!

    Source = Json.Document(Web.Contents(Text.Combine({"###YOUR HOSTED FEATURE LAYER FEATURESERVICE URL###/query?where=1%3D1&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&resultType=none&distance=0.0&units=esriSRUnit_Meter&returnGeodetic=false&outFields=*&returnHiddenFields=false&returnGeometry=true&featureEncoding=esriDefault&multipatchOption=xyFootprint&maxAllowableOffset=&geometryPrecision=&outSR=&defaultSR=&datumTransformation=&applyVCSProjection=false&returnIdsOnly=false&returnUniqueIdsOnly=false&returnCountOnly=false&returnExtentOnly=false&returnQueryGeometry=false&returnDistinctValues=false&cacheHint=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&having=&resultOffset=&resultRecordCount=&returnZ=false&returnM=false&returnExceededLimitFeatures=true&quantizationParameters=&sqlFormat=none&f=pjson&token=", token}))),
    fields = Source[fields],
    #"Converted to Table" = Table.FromList(fields, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"name", "type", "alias", "sqlType", "domain", "defaultValue"}, {"name", "type", "alias", "sqlType", "domain", "defaultValue"}),
    #"Filter for Domains" = Table.SelectRows(#"Expanded Column1", each ([domain] <> null)),
    #"Expand Domains" = Table.ExpandRecordColumn(#"Filter for Domains", "domain", {"type", "name", "codedValues"}, {"domain.type", "domain.name", "domain.codedValues"}),
    #"Expanded Domain Coded Values" = Table.ExpandListColumn(#"Expand Domains", "domain.codedValues"),
    #"Unpivot Coded Values" = Table.ExpandRecordColumn(#"Expanded Domain Coded Values", "domain.codedValues", {"name", "code"}, {"domain.codedValues.name", "domain.codedValues.code"}),
    #"Renamed Columns3" = Table.RenameColumns(#"Unpivot Coded Values",{{"name", "Field Domain"}, {"domain.codedValues.name", "Domain Name"}, {"domain.codedValues.code", "Domain Code"}}),
    #"Domain Coded Value" = Table.SelectColumns(#"Renamed Columns3",{"Field Domain", "Domain Code", "Domain Name"}),
    #"Expanded Column2" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"name", "type", "alias", "sqlType", "domain", "defaultValue", "length"}, {"name", "type", "alias", "sqlType", "domain", "defaultValue", "length"}),
    #"Removed Columns" = Table.RemoveColumns(#"Expanded Column2",{"type", "sqlType", "domain", "defaultValue", "length"}),
    #"Column Names Lookup List" = Table.ToRows(#"Removed Columns"),
    features = Source[features],
    #"Converted to Table1" = Table.FromList(features, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column3" = Table.ExpandRecordColumn(#"Converted to Table1", "Column1", {"geometry"}, {"geometry"}),
    #"Expanded geometry" = Table.ExpandRecordColumn(#"Expanded Column3", "geometry", {"x", "y"}, {"x", "y"}),
    #"Added Index" = Table.AddIndexColumn(#"Expanded geometry", "Index", 0, 1, Int64.Type),
    #"Expanded Column4" = Table.ExpandRecordColumn(#"Converted to Table1", "Column1", {"attributes"}, {"attributes"})
    #"Expanded Column4"

Once you've replaced the ###PLACEHOLDERS### from my example code with your parameters click Done You will now need to expand the single column of Records into a table by clicking to the right of the column name. It's a button with two opposite arrows. Click OK and you will see your data. Now click Close & Load You will now see a worksheet with the same name as the query you just made with your data in it. You can refresh your data by clicking the Refresh All button on the Data tab or configure the query to Refresh data when opening the file in the properties of the query in the Queries & Connections window.

PS - this also works for Power BI

Good Luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.