Skip to content

Hyundai Kia: Refresh Token

Michael Panzer edited this page Feb 16, 2026 · 5 revisions

bluelink_refresh_token

This scripts helps owners of cars made by Hyundai or Kia to retrieve the refresh_token that is now necessary to access the Bluelink API in the integrations for HomeAssistant and evcc.

It is a combination of the separate efforts of @fuatakgun (original Kia implementation) and @Maaxion (Hyundai aption)

Prerequisites

You need to have the following installed on your computer

Important

On Windows installations make sure to set the check at "Add Python 3.x to PATH" in the installer

  1. Python3 >= 3.12
  2. wget (Linux/MacOS) or iwr (Windows)
  3. Chrome or a Chromium based Brower

Preparations

  1. Copy the script from below to your local hard drive:

    1. Linux/MacOS
      wget -O bluelinktoken.py https://raw.githubusercontent.com/RustyDust/bluelink_refresh_token/refs/heads/main/bluelinktoken.py
    2. Windows
      Run in powershell:
      iwr -UseBasicParsing -OutFile bluelinktoken.py https://raw.githubusercontent.com/RustyDust/bluelink_refresh_token/refs/heads/main/bluelinktoken.py
  2. Prepare the python runtime environment (you do have Python3 installed, right?)

    1. Linux/MacOS

      python3 -m venv .venv
      source .venv/bin/activate
      pip3 install selenium requests
    2. Windows

      Do not double click the python file to run it. If you do, the terminal will close after the program ends, giving you no chance to copy the refresh token.

      Open cmd in the same dir you downloaded the Python file into (or continue in the powershell from the previous step):

      python -m venv .venv
      .\.venv\Scripts\Activate.ps1
      python -m pip install --upgrade pip
      pip install selenium requests webdriver-manager

Running the Script

Note

You should still be in the Python environment from step 2.1 or 2.2 from above!

Kia

  1. Linux/MacOS:
    python ./bluelinktoken.py --brand kia
  2. Windows:
    python .\bluelinktoken.py --brand kia

Hyundai

  1. Linux/MacOS:
    python ./bluelinktoken.py --brand hyundai
  2. Windows:
    python .\bluelinktoken.py --brand hyundai

The script will automatically open your browser (you did install Chrome, yes?) with the correct URL for your vehicle's brand. Log in using the credentials (username / password) you use in the app on your mobile phone.

If everything worked as expected you'll get an output in your terminal similar to this:

Opening login page: https://idpconnect-eu.(kia/hyundai).com/auth/api/v2/user/oauth2/authorize?(...shortened...)

==================================================
Please log in manually in the browser window.
The script will wait for you to complete the login...
==================================================

✅ Login successful! Element found.

✅ Your tokens are:

- Refresh Token: M2M2OG................................YOTG5
- Access Token: eyJhbGc.........................0_AijpHXp0yg
Cleaning up and closing the browser.

Usage in Home Assistant or evcc

Use the Refresh Token from above as the password together with your normal username when setting up either the HomeAssistant or evcc integration for your vehicle.

Note

The refresh token you generated is valid for 180 days. After that period you'll have to generate a new one and reconfigure your integrations

macOS on arm Chrome issue

On macOS by default the x86 emulated Chrome is opened by selenium and that's so slow that it doesn't really work. Here is a all in one workaround script that just needs to be executed. It could be that you need to go the Systemsettings > Security to allow for the chromedriver to be executed.

#!/bin/zsh
set -e

# Define variables
FILENAME="bluelinktoken.py"
URL="https://raw.githubusercontent.com/RustyDust/bluelink_refresh_token/refs/heads/main/bluelinktoken.py"

# Check if the file already exists
if [ -f "$FILENAME" ]; then
    echo "File '$FILENAME' already exists."
    echo "Skipping download and patch to avoid overwriting your current file."
else
    echo "File not found. Proceeding with download..."
    
    # Download with curl
    curl -L -o "$FILENAME" "$URL"

    # Verify download succeeded before patching
    if [ -f "$FILENAME" ]; then
        echo "Download complete. Patching file..."
        
        # Use perl to insert the 'service' line and the updated 'driver' line
        # keeping the original indentation ($1)
        perl -i -pe 's/^(\s*)driver = webdriver\.Chrome\(options=options\)/$1service = webdriver.ChromeService(port=54130)\n$1driver = webdriver.Chrome(service=service, options=options)/' "$FILENAME"
        
        echo "Success! The file has been downloaded and updated."
    else
        echo "Error: Download failed."
    fi
fi

# --- STEP 1: Detect OS and Architecture for Chromedriver ---
echo "--- Checking System Configuration ---"
OS="$(uname -s)"
ARCH="$(uname -m)"
PLATFORM=""

if [[ "$OS" == "Darwin" ]]; then
    if [[ "$ARCH" == "arm64" ]]; then
        PLATFORM="mac-arm64" # Apple Silicon
    else
        PLATFORM="mac-x64"   # Intel Mac
    fi
elif [[ "$OS" == "Linux" ]]; then
    PLATFORM="linux64"
else
    echo "Error: Unsupported OS ($OS)"
    exit 1
fi

echo "Detected Platform: $PLATFORM"

# --- STEP 2: Download & Unzip Latest Stable Chromedriver ---
echo "--- Downloading latest Chromedriver Stable ---"

# We use Python to parse the official JSON to get the exact download URL for your platform
JSON_URL="https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json"

DOWNLOAD_URL=$(curl -s "$JSON_URL" | python3 -c "
import sys, json
data = json.load(sys.stdin)
# Find the URL for the 'Stable' channel matching our platform
downloads = data['channels']['Stable']['downloads']['chromedriver']
url = next(item['url'] for item in downloads if item['platform'] == '$PLATFORM')
print(url)
")

echo "Downloading from: $DOWNLOAD_URL"
curl -L -o chromedriver.zip "$DOWNLOAD_URL"

echo "Unzipping..."
# Unzip quietly (-q) and overwrite (-o)
unzip -q -o chromedriver.zip

mv chromedriver-mac-arm64/chromedriver chromedriver
chmod +x chromedriver

rm -rf chromedriver-mac-arm64
rm -rf chromedriver.zip

echo "Chromedriver updated successfully."

# --- STEP 3: Setup Python Environment ---
echo "--- Setting up Python VENV ---"

if [[ ! -d ".venv" ]]; then
    echo "Creating virtual environment..."
    python3 -m venv .venv
fi

source .venv/bin/activate
pip install -q selenium requests

# --- STEP 4: Start Background Process & Trap ---
echo "--- Starting Chromedriver Background Service ---"

# Note: We use ./chromedriver to ensure we use the one we just downloaded
./chromedriver --port=54130 &
CHROMEDRIVER_PID=$!

# Define cleanup to kill chromedriver on exit
cleanup() {
    echo "\n--- Stopping chromedriver (PID: $CHROMEDRIVER_PID) ---"
    kill "$CHROMEDRIVER_PID" 2>/dev/null
}
trap cleanup EXIT INT TERM

# Wait a moment for chromedriver to spin up
sleep 2

# --- STEP 5: Run Main Script ---
echo "--- Running Bluelink Token Script ---"
python ./bluelinktoken.py --brand hyundai

Clone this wiki locally