10REM / php-garmin-connect

A PHP adapter for interrogating the Garmin Connect "API"
MIT License
84 stars 41 forks source link

Anyone getting 403 error from Garmin Connect starting today? #61

Open fulmar2 opened 1 year ago

fulmar2 commented 1 year ago

The code has been working for a while, but today started getting a 403 error from Garmin Connect. Anyone else experiencing that?

cabby26 commented 1 year ago

Same

ltcomd commented 1 year ago

Same here. Some days ago it was working...

fulmar2 commented 1 year ago

I am guessing that Garmin changed the URL. But i don’t know how to figure out what the new URL is (assuming they still support this).

DaveWilcock commented 1 year ago

Are you getting a 403 when trying to login or is it a 403 when performing one of the requests for data?

fulmar2 commented 1 year ago

Seems like this URL at least produces a blank page:

https://connect.garmin.com/modern/proxy/activitylist-service/activities/search/activities

I log in using a browser and try to visit this URL and it is just two HTML tags. No error is generated during the log in process that I know of…

DaveWilcock commented 1 year ago

Seems like this URL at least produces a blank page:

https://connect.garmin.com/modern/proxy/activitylist-service/activities/search/activities

I log in using a browser and try to visit this URL and it is just two HTML tags. No error is generated during the log in process that I know of…

I'm not sure if this is new, but a request to the search endpoint here in the browser, looks like it's passing a bearer token in the request header, which indicates that this search endpoint is now behind some auth mechanism. Will do some more investigation when I've got some time.

anniew86 commented 1 year ago

perhaps it should be https://connect.garmin.com/activitylist-service/activities/ ... ?

fulmar2 commented 1 year ago

perhaps it should be https://connect.garmin.com/activitylist-service/activities/ ... ?

Thanks, I just tried that link which produces an error page. Appreciate the suggestion, though.

teibaz commented 1 year ago

I can see that everyone who uses garmin connect in all programming languages faces the same issue. I found very nice options here: https://github.com/pe-st/garmin-connect-export/issues/95

but it takes time to test and develop everything. If someone will do the same - let us know, otherwise I will try to sit this weekend and try to change the code.

anniew86 commented 1 year ago

here some other issues (and solutions) mostly for python clients:

https://github.com/petergardfjall/garminexport/issues/102 https://github.com/petergardfjall/garminexport/issues/103 https://github.com/petergardfjall/garminexport/pull/104 https://github.com/petergardfjall/garminexport/pull/105 https://github.com/cyberjunky/python-garminconnect/pull/144

fulmar2 commented 1 year ago

here some other issues (and solutions) mostly for python clients:

petergardfjall/garminexport#102 petergardfjall/garminexport#103 petergardfjall/garminexport#104 petergardfjall/garminexport#105 cyberjunky/python-garminconnect#144

Thanks for the links anniew. Do you see how to integrate Garth with this PHP project? I’m at a loss.

jpgnz commented 1 year ago

Not easily. Essentially there needs to be a rewrite of a large chunk of the authentication workflow of this library to match what Garth is doing in Python.

DaveWilcock commented 1 year ago

I’ll take a look tonight and see what’s what.

On Mon, 16 Oct 2023 at 15:33, James @.***> wrote:

Not easily. Essentially there needs to be a rewrite of a large chunk of the authentication workflow of this library to match what Garth is doing in Python.

— Reply to this email directly, view it on GitHub https://github.com/10REM/php-garmin-connect/issues/61#issuecomment-1764614560, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADHRHXCQ7VN6C2GZDZ55R3X7VATXAVCNFSM6AAAAAA5IEUKSCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONRUGYYTINJWGA . You are receiving this because you commented.Message ID: @.***>

--

Chip Financial Ltd (“Chip”) is registered in England and Wales, registration number:

10113174

Our registered office is: Chip Financial Ltd, Sixth Floor,Fora Montacute Yards, 186 Shoreditch High Street, London, E1 6HU

Note that Chip is not a bank, meaning that we do not have physical branches, issue debit bank cards nor are you able to access your Chip money via ATMs. Chip does not provide financial advice and our services are only available via the Chip app.

Chip is a trading name of Chip Financial Ltd and is authorised by the Financial Conduct Authority under the Payment Services Regulation 2017 for the provision of payment services. Firm Reference Number 911255.

jpgnz commented 1 year ago

@DaveWilcock I found this comment pretty useful: https://github.com/petergardfjall/garminexport/pull/104#issuecomment-1742123856

I got curl-impersonate to compile and have it loaded into my php install (docs here) and was hopeful it would just work like the comment suggested on their library, but it didn't, same 403 error. I was going to attempt to see what else I might need to adjust in your library but I ran out of time.

I don't think it's necessarily feasible for all users to be able to compile and adjust their php configuration, but unsure. For me it would be completely acceptable to require that.

The Garth solution definitely appears to be the best long term way as it seems to impersonate the mobile application, but looks like quite a bit of work.

anniew86 commented 1 year ago

Thanks for the links anniew. Do you see how to integrate Garth with this PHP project? I’m at a loss.

Hi,

I was able to integrate the python solution https://github.com/cyberjunky/python-garminconnect (thank you very much cyberjunky ) with my own PHP program. It is not Garth alone but a very helpful python project which is using Garth.

Below step-by-step description of my approach, please keep in mind, that I'm using Linux Debian.

1) install python and pip (python packet manager): $ apt-get install python3 pip

2) install python package 'garminconnect' and dependecies in the local directory 'python_packages': $ pip install --target=python_packages garminconnect

3) create the python script 'garmin.py' with execution rights, which will be called from php, the script can be called with 4 params, calls 3 possible api's and returns the response with json, here the content:

#!/usr/bin/env python3

import sys
import os
import json
from garth.exc import GarthHTTPError
from garminconnect import (
    Garmin,
    GarminConnectAuthenticationError,
    GarminConnectConnectionError,
    GarminConnectTooManyRequestsError,
)

userid = sys.argv[1]
password = sys.argv[2]
command = sys.argv[3]

tokenstore = os.getcwd() + '/garmin_tokenstore/' + userid

def init_api(email, password):

    try:
        # Trying to login to Garmin Connect using token data from '{tokenstore}'
        garmin = Garmin()
        garmin.login(tokenstore)
    except (FileNotFoundError, GarthHTTPError, GarminConnectAuthenticationError):
        # Login tokens not present or session is expired, login with your Garmin Connect credentials to generate them
        # They will be stored in '{tokenstore}' for future use.
        try:
            garmin = Garmin(email, password)
            garmin.login()
            # Save tokens for next login
            garmin.garth.dump(tokenstore)

        except (FileNotFoundError, GarthHTTPError, GarminConnectAuthenticationError, requests.exceptions.HTTPError) as err:
            logger.error(err)
            return None

    return garmin

api = init_api(userid, password)

if command == 'getActivityList':
    count = sys.argv[4]
    response = api.get_activities(0,count)
    print(json.dumps(response))
elif command == 'getActivity':
    activity_id = sys.argv[4]
    response = api.get_activity_evaluation(activity_id)
    print(json.dumps(response))
elif command == 'getActivityWeather':
    activity_id = sys.argv[4]
    response = api.get_activity_weather(activity_id)
    print(json.dumps(response))
else:
    print('invalid command')    

4) call the script from PHP in such way:

  $userid = 'YOUR_GARMIN_USER';
  $password = 'YOUR_GARMIN_PASS';
  $count = 10;
  $home = getcwd();  
  $response_json = shell_exec( "PYTHONPATH=python_packages {$home}/garmin.py $userid $password getActivityList $count" );
  echo json_decode($response_json, true);

It is a workaround for me, if possible I would like to use back this PHP project and have a pure PHP solution,

I hope it helps, Annie

hogeh commented 1 year ago

Anybody with a php solution meanwhile?? Desperately waiting for it...Thanks to everybody who helps to get this working again! Ho

fulmar2 commented 1 year ago

Not sure this is any help, but I ended up using their API. I signed up as a developer, and got my codes. The app got approved; this part was easy. Trying to learn the API with the paucity of documentation was difficult… but in a nutshell, Garmin will “ping” your web hook when a new activity is uploaded. The ping contains a json that only has a little information, but one item is a special URL for the activity - which includes an activity ID (that does NOT match the activity ID that you are used to) and a token. All of this is a major pain to learn, but over the course of a few days and another php Garmin connector on git hub, I was able to get it to work. Now that it is working, I am glad I chose that route instead of relying on the spoof browser method. I really love that creative people have worked so hard on this project, but as it is written now, it will continue to break whenever Garmin changes their website.

teibaz commented 1 year ago

I had no time and ended up using python-garminconnect by cyberjunky - once the file is in server all the parsing part and the rest project is being done by php as before.

ChristianManunzio commented 1 year ago

Not sure this is any help, but I ended up using their API. I signed up as a developer, and got my codes. The app got approved; this part was easy. Trying to learn the API with the paucity of documentation was difficult… but in a nutshell, Garmin will “ping” your web hook when a new activity is uploaded. The ping contains a json that only has a little information, but one item is a special URL for the activity - which includes an activity ID (that does NOT match the activity ID that you are used to) and a token. All of this is a major pain to learn, but over the course of a few days and another php Garmin connector on git hub, I was able to get it to work. Now that it is working, I am glad I chose that route instead of relying on the spoof browser method. I really love that creative people have worked so hard on this project, but as it is written now, it will continue to break whenever Garmin changes their website.

Can you share which garmin connector on github you used to learn this? I´m still struggeling to get it to work 🙈

fulmar2 commented 1 year ago

Christian-

i installed this:

https://github.com/stoufa06/php-garmin-connect-api

It did not work initially, as I had to make a change to one line of code as described here (uriFor vs uri_for):

https://github.com/stoufa06/php-garmin-connect-api/issues/12

That will save you a lot of time!

Once I got the example working, it gives me a summary of activities. Quite happy with that… but then i used my Garmin API Developer account, and from there I can manage “pings” from the API to my webhooks. All new activities come to my specified URL (by the way, you will have to dig on the Garmin developer page to find your API settings to specify the endpoints).

Now that I have done all this work, I am quite happy, and feel like my tools will be more reliable in the future. It’s a 100% PHP solution.

DaveWilcock commented 1 year ago

Thanks for this info Brian. Do you know if the developer access to their APIs is limited in any way? e.g. by time or API call rate limiting, etc.

On Fri, 27 Oct 2023 at 12:48, Brian @.***> wrote:

Christian-

i installed this:

https://github.com/stoufa06/php-garmin-connect-api

It did not work initially, as I had to make a change to one line of code as described here (uriFor vs uri_for):

stoufa06/php-garmin-connect-api#12 https://github.com/stoufa06/php-garmin-connect-api/issues/12

That will save you a lot of time!

Once I got the example working, it gives me a summary of activities. Quite happy with that… but then i used my Garmin API Developer account, and from there I can manage “pings” from the API to my webhooks. All new activities come to my specified URL (by the way, you will have to dig on the Garmin developer page to find your API settings to specify the endpoints).

Now that I have done all this work, I am quite happy, and feel like my tools will be more reliable in the future. It’s a 100% PHP solution.

— Reply to this email directly, view it on GitHub https://github.com/10REM/php-garmin-connect/issues/61#issuecomment-1782778637, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADHRHQEJKVJG56G3MG3G4LYBONQDAVCNFSM6AAAAAA5IEUKSCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTOOBSG43TQNRTG4 . You are receiving this because you were mentioned.Message ID: @.***>

--

Chip Financial Ltd (“Chip”) is registered in England and Wales, registration number:

10113174

Our registered office is: Chip Financial Ltd, Sixth Floor,Fora Montacute Yards, 186 Shoreditch High Street, London, E1 6HU

Note that Chip is not a bank, meaning that we do not have physical branches, issue debit bank cards nor are you able to access your Chip money via ATMs. Chip does not provide financial advice and our services are only available via the Chip app.

Chip is a trading name of Chip Financial Ltd and is authorised by the Financial Conduct Authority under the Payment Services Regulation 2017 for the provision of payment services. Firm Reference Number 911255.

fulmar2 commented 1 year ago

Thanks for this info Brian. Do you know if the developer access to their APIs is limited in any way? e.g. by time or API call rate limiting, etc.

Dave - I am signed up for an evaluation account. I did not see an easy way to migrate to a production account, but maybe it does not matter. I actually created the developer portal account 28 months ago last time your code was broken by Garmin. There may be rate limiting, but I cannot find any information about that online. As you know, their documentation is very opaque. It seems that their API works in two ways.

One way is that you can send requests using the https://github.com/stoufa06/php-garmin-connect-api tool. The other way is (once you have an account), for any user who has agreed to share their data, new activities can be "pinged" to a webhook you specify here:

https://apis.garmin.com/tools/login (note that you need an approved account to log in here)

You manage your app/team here:

https://developerportal.garmin.com/

To me, it seems pretty round-about, and definitely not "clean". Having worked with the Strava API, I find it much more intuitive... but this is what we are faced with. I hope this helps others. Also, Dave: Thanks for your work all these years keeping this project working. Really appreciate it.

stoufa06 commented 2 months ago

@fulmar2 Thank you for the mention The gamin api package that i am actually using has much more features and well maintained. I have developed it but i can not share it. This package is just an example of work https://github.com/stoufa06/php-garmin-connect-api that i have created it on my own time. If you want good advice from my own experience with garmin:

If anyone needs help with garmin api thing i have an upwork account so you can hire me.