> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gbox.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Appium Connection

> Generate a pre-signed proxy URL for Appium server of a running Android box.



## OpenAPI

````yaml post /boxes/{boxId}/android/connect-url/appium
openapi: 3.0.0
info:
  title: GBOX Open API
  description: GBOX Open API Documentation
  version: '1.0'
  contact: {}
servers:
  - url: https://gbox.ai/api/v1
    description: Production Server
security: []
tags: []
paths:
  /boxes/{boxId}/android/connect-url/appium:
    post:
      tags:
        - Android
      summary: Generate Appium connection URL
      description: >-
        Generate a pre-signed proxy URL for Appium server of a running Android
        box.
      operationId: AndroidController_getAppiumConnectUrl
      parameters:
        - name: boxId
          required: true
          in: path
          description: Box ID
          schema:
            example: c9bdc193-b54b-4ddb-a035-5ac0c598d32d
            type: string
      requestBody:
        required: false
        description: Generate Appium connection URL
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GenerateAppiumUrl'
      responses:
        '200':
          description: Appium connection information
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AppiumConnectInfo'
      security:
        - bearer: []
      x-codeSamples:
        - lang: JavaScript
          source: |-
            import webdriverio from 'webdriverio';
            import GboxSDK from "gbox-sdk";

            const gboxSDK = new GboxSDK({
              apiKey: process.env["GBOX_API_KEY"] // This is the default and can be omitted
            });

            async function main() {
              const box = await gboxSDK.create({ type: "android" });

              const { url, defaultOption } = await box.appiumURL();

              console.log("Appium connection URL:", url);

              // Connect to Appium with defaultOption from backend
              console.log("Connecting to Appium server...");
              const ac = await remote(defaultOption);

              console.log("✅ Successfully connected to Appium server");
              console.log("Session ID:", ac.sessionId);

              try {
                // Get current page XML layout
                console.log("Fetching XML layout...");
                const xmlLayout = await ac.getPageSource();
                
                console.log("✅ XML layout fetched successfully!");
                console.log("XML length:", xmlLayout.length, "characters");
                
                // Display a preview of the XML (first 500 characters)
                console.log("\n--- XML Layout Preview (first 500 chars) ---");
                console.log(xmlLayout.substring(0, 500) + "...\n");
                
                // Save XML to file for easier viewing
                const outputDir = path.join(__dirname, "output");
                if (!fs.existsSync(outputDir)) {
                  fs.mkdirSync(outputDir, { recursive: true });
                }
                
                const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
                const filename = `layout_${timestamp}.xml`;
                const filepath = path.join(outputDir, filename);
                
                fs.writeFileSync(filepath, xmlLayout, "utf-8");
                console.log(`📁 XML layout saved to: ${filepath}`);
                
                // Optional: Parse and display some basic info
                const elementMatches = xmlLayout.match(/<[\w.-]+/g);
                if (elementMatches) {
                  const elementSet = new Set(elementMatches.map(e => e.substring(1)));
                  const uniqueElements = Array.from(elementSet);
                  console.log("\n--- UI Elements Found ---");
                  console.log("Total elements:", elementMatches.length);
                  console.log("Unique element types:", uniqueElements.length);
                  console.log("Element types:", uniqueElements.slice(0, 10).join(", "), "...");
                }
                
              } catch (error) {
                console.error(
                  "❌ Error fetching XML layout:",
                  error instanceof Error ? error.message : String(error)
                );
              } finally {
                console.log("\nClosing session...");
                await ac.deleteSession();
                console.log("Session closed.");
              }
            }

            main()
        - lang: Python
          source: |-
            import os
            from appium import webdriver
            from gbox_sdk import GboxSDK

            # Initialize GboxSDK (synchronous API)
            gbox_sdk = GboxSDK(
                api_key=os.environ.get("GBOX_API_KEY")  # This is the default and can be omitted
            )

            def main():
                # Create a box (synchronous)
                box = gbox_sdk.create(type="android")
                
                # Get Appium connection URL (synchronous)
                result = box.appium_url()
                url = result["url"]
                default_option = result["default_option"]
                
                print("Appium connection URL:", url)
                
                # Connect to Appium with defaultOption from backend
                print("Connecting to Appium server...")
                driver = webdriver.Remote(
                    command_executor=url,
                    desired_capabilities=default_option["capabilities"]
                )
                
                print("✅ Successfully connected to Appium server")
                print("Session ID:", driver.session_id)
                
                try:
                    # Get current page XML layout
                    print("Fetching XML layout...")
                    xml_layout = driver.page_source
                    
                    print("✅ XML layout fetched successfully!")
                    print("XML length:", len(xml_layout), "characters")
                    
                    # Display a preview of the XML (first 500 characters)
                    print("\n--- XML Layout Preview (first 500 chars) ---")
                    print(xml_layout[:500] + "...\n")
                    
                    # Save XML to file for easier viewing
                    import os
                    from datetime import datetime
                    
                    output_dir = os.path.join(os.path.dirname(__file__), "output")
                    if not os.path.exists(output_dir):
                        os.makedirs(output_dir, exist_ok=True)
                    
                    timestamp = datetime.now().isoformat().replace(":", "-").replace(".", "-")
                    filename = f"layout_{timestamp}.xml"
                    filepath = os.path.join(output_dir, filename)
                    
                    with open(filepath, "w", encoding="utf-8") as f:
                        f.write(xml_layout)
                    print(f"📁 XML layout saved to: {filepath}")
                    
                    # Optional: Parse and display some basic info
                    import re
                    element_matches = re.findall(r'<[\w.-]+', xml_layout)
                    if element_matches:
                        element_set = set(e[1:] for e in element_matches)
                        unique_elements = list(element_set)
                        print("\n--- UI Elements Found ---")
                        print("Total elements:", len(element_matches))
                        print("Unique element types:", len(unique_elements))
                        print("Element types:", ", ".join(unique_elements[:10]), "...")
                    
                except Exception as error:
                    print(f"❌ Error fetching XML layout: {str(error)}")
                finally:
                    print("\nClosing session...")
                    driver.quit()
                    print("Session closed.")

            if __name__ == "__main__":
                main()
        - lang: Go
          source: |-
            package main

            import (
                "bytes"
                "encoding/json"
                "fmt"
                "net/http"
            )

            func main() {
                url := "/api/v1/boxes/{boxId}/android/connect-url/appium"

                payload := map[string]interface{}{
                    // Optional: Add any specific parameters if needed
                }

                jsonData, _ := json.Marshal(payload)

                req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
                req.Header.Set("Content-Type", "application/json")
                req.Header.Set("Authorization", "Bearer YOUR_API_KEY")

                client := &http.Client{}
                resp, _ := client.Do(req)
                defer resp.Body.Close()

                var result map[string]interface{}
                json.NewDecoder(resp.Body).Decode(&result)

                fmt.Println("Appium connection URL:", result["url"])
            }
components:
  schemas:
    GenerateAppiumUrl:
      type: object
      properties:
        expiresIn:
          type: string
          description: >-
            The Appium connection url will be alive for the given duration


            Supported time units: ms (milliseconds), s (seconds), m (minutes), h
            (hours)

            Example formats: "500ms", "30s", "5m", "1h"

            Default: 120m
          example: 120m
          default: 120m
          title: GenerateAppiumUrlConfig
      title: Generate Appium Url
      description: Generate Appium connection url
    AppiumConnectInfo:
      type: object
      properties:
        url:
          type: string
          description: Appium connection URL
          example: https://gbox.ai/api/share/v1/proxy/tmp_token123/appium
        udid:
          type: string
          description: Device UDID for Appium connection
          example: emulator-5554
        defaultOption:
          description: A ready-to-use default WebdriverIO remote options object
          example:
            protocol: https
            hostname: gbox.ai
            port: 443
            path: /api/share/v1/proxy/tmp_token123/appium
            capabilities:
              platformName: Android
              appium:automationName: UiAutomator2
              appium:udid: emulator-5554
              appium:deviceName: emulator-5554
          allOf:
            - $ref: '#/components/schemas/AppiumDefaultOption'
        logLevel:
          type: string
          description: Log level for WebdriverIO/Appium client
          enum:
            - trace
            - debug
            - info
            - warn
            - error
            - silent
          example: error
          default: error
      title: Appium Connect Info
      description: Appium connection information
      required:
        - url
        - udid
        - defaultOption
        - logLevel
    AppiumDefaultOption:
      type: object
      properties:
        protocol:
          type: string
          description: Protocol (http or https)
          example: https
        hostname:
          type: string
          description: Hostname
          example: gbox.ai
        port:
          type: number
          description: Port number
          example: 443
        path:
          type: string
          description: URL pathname
          example: /api/share/v1/proxy/tmp_token123/appium
        capabilities:
          description: Appium capabilities
          example:
            platformName: Android
            appium:automationName: UiAutomator2
            appium:udid: emulator-5554
            appium:deviceName: emulator-5554
          allOf:
            - $ref: '#/components/schemas/AppiumCapabilities'
      title: Appium Default Option
      description: Ready-to-use WebdriverIO remote options
      required:
        - protocol
        - hostname
        - port
        - path
        - capabilities
    AppiumCapabilities:
      type: object
      properties:
        platformName:
          type: string
          description: Platform name
          example: Android
        appium:automationName:
          type: string
          description: Appium automation name
          example: UiAutomator2
        appium:udid:
          type: string
          description: Device UDID
          example: emulator-5554
        appium:deviceName:
          type: string
          description: Device name
          example: emulator-5554
      title: Appium Capabilities
      description: Appium capabilities for WebdriverIO
      required:
        - platformName
        - appium:automationName
        - appium:udid
        - appium:deviceName
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: JWT
      type: http
      description: >-
        Enter your API Key in the format: Bearer <token>. Get it from
        https://gbox.ai

````