I have my runs set to sync from Paiactive to Strava; but can not sync past runs and there is no export option within the app.

The main options:

  • check to see if the file is stored locally on the phone, but requires root access.
  • check if there is a website to download the data from, but there is not.
  • intercept the traffic to capture the data as it is loaded

The third option is the only viable option, and that the run data was stored remotely was indicated by a delay in the app displaying the run data suggesting it was stored remotely.

The steps to take:

  • install mitm proxy
  • point phone to proxy server
  • use the app and analyse the traffic between phone and server

Using the mitmweb tools on the server I can see traffic succesfully, and just how much data is transmitted from my phone to a whole multiude of servers!

Anyway, curiosuly the login request from the app is as follows:

POST https://lseur.laisitech.com/account/login?appId=129XXXXXX288&timestamp=1642XXXXXX310&version=v1&language=en&sign=D28A156EC0B2430BF9E38C12345D670C HTTP/1.1
{
    "deviceId":	"e3SdaUZdRAafe6pVXnSdRW:APA93dHUm33FBl3Y3jU8dApQgdaA9ZNdMamaVaAa3BaE_ZdMX3DMikO7RmNadNakaLJ8SZaaeZ7XT-qBak3aAMTpadaAdm6RddkCk3Da-adhL0H8NQERanaoEaTlJF9j3SPhaIgaTdaq",
    "email": "user@example.com",
    "password": "ABC0D98D72434E88E1F9805BD63321A"
}

The issue being that I am not sure how the ‘sign=’ is generated and so can only replay messages to the server where I know the full data being sent, and the full HTTP POST details including the value of ‘sign’.

If I could work out how the ‘sign’ is generated, I could make an app in whatever language to login in the future without having to use a proxy.

That being said, I can still replay the request with curl once I have captured it with the proxy.

So on my phone I browse to my running history, select a date and then a particular run. This is downloaded to the phone with the traffic being visible in the proxy.

mitmweb list of requests mitmweb request details

I can then copy and save the request data JSON into a file, and use the POST request details to replay the request with curl. There is a limited opportunity to do so though as each request is timestamped and faces expiry. Any new request from the app will have a new timestamp, and new sign value.

curl "https://lseur.laisitech.com/sportwatch/run/detail?appId=129XXXXXXXXX\
&timestamp=1612319141933\
&version=v1\
&timeZone=Europe%2FParis\
&token=dtG0eZAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.dtG1aWQiOiIxMDAwMzYyOSIsInR5cGUiOiJhY2Nlc3NUb2tlbiIsImlzcyI6IlBoaWNvbW0iLCJuYmYiOjE2NDIyMjA2NTUsImV4cCI6MTY0MjczOTA1NSwicmVmcmVzaFRpbWUiOiIyMDIyLTAxLTE3IDA0OjI0OjE1In0.l1dY5uIWetOwTj8tzJ-FKpxKiv1C1icUiOvSHBnM6N5\
&userId=10003XXX\
&platform=android\
&appVersion=1.0.2074\
&language=en\
&sign=A12419C5BC315B7C533A5818F8C4DDA7" \
  -H 'Accept: :	gzip, deflate' \
  -H 'Content-Type: application/json; charset=utf-8' \
  -H 'Host: lseur.laisitech.com' \
  -H 'Connection: Keep-Alive' \
  -H 'User-Agent: okhttp/5.0.0-alpha.2' \
  --data @request.json \
  --output response.json.gz

Alternatively, I can now use the package mitmdump to run a python script which will do the hard work for me, useful when trying to get a whole bunch of run history.

I can even use the python script to decompress the data response into plain text/JSON and then manipulate that into a GPX (XML based) file.

Running from a windows command prompt, I can launch the script and proxy with:

mitmdump --quiet --flow-detail 0 --scripts mitm-paiactive.py "~u https://lseur.laisitech.com/"

Then, as I’m using the app on my phone, the output directory is filling with GPX files for each run which I can then upload manually to Strava.

Included below is the script; mitm-paiactive.py