Extracting Every Part of an Oracle APEX URL in JavaScript

Matt MulvaneyMatt Mulvaney
5 min read

I have encountered this problem from time to time, so finally I want to solve it once and for all.

The problem is that I want to fetch every part of the APEX URL. So that I can use it in JS for use in App Development, Plugins, User scripts, etc.

Example problems my include:

  • I need a URL that starts with either /pls/apex (for apex.oracle.com) or /ords or whatever the middle-ware guys have named the ords server

  • I need to grab and check the URL parameters for whatever reason

  • I just need to produce a partial URL in JS

Usually I just find a workaround, something quick, that I think works. But today… enough with that. Please see below a solution that:

  • Outputs a bunch of APEX URL related attributes

  • It attempts to reconstruct the URL, comparing against the original, to test its valid

  • Supports both Classic & Friendly URLs

The idea is that you run the code and take what you need from it.

The Object it outputs returns the following

  • protocol:
    The URL protocol (e.g. "https:").

  • hostname:
    The domain name (e.g. "example").

  • port:
    The port number (e.g. "443"), or an empty string if not specified.

  • fullUrl:
    The original full URL passed to the function (or window.location.href by default).

  • fullUrlReconstructed:
    The reconstructed URL, built from the protocol, hostname, port, pathname, and search parameters.

  • reconstructionValid:
    Boolean indicating if the original URL and the reconstructed URL are identical.

  • isFParamUrl:
    Boolean indicating if the URL uses the classic APEX f?p=... format (non-friendly URL).

  • appId:
    The Application ID (from the URL or f?p=...).

  • pageId:
    The Page ID (from apex.env.APP_PAGE_ID for classic URLs, or from the friendly URL if available).

  • pageAlias:
    The Page Alias (for classic URLs, only set if the value in the URL does not match the real page ID).

  • sessionId:
    The Session ID (from apex.env.APP_SESSION if available, otherwise from the URL).

  • request:
    The request value (from the classic URL’s f?p=...).

  • workspace:
    For friendly URLs: the workspace or language segment after /r/.

  • appAlias:
    For friendly URLs: the application alias segment after /r/.

  • serviceName:
    For classic URLs: the first path segment (e.g., "ords").
    For friendly URLs: everything between the domain and /r/.

  • pathParts:
    An array of all path segments in the URL.

  • baseIndex:
    The index in pathParts where the main application-specific segments start (after /r/ for friendly URLs).

  • apexEnv:
    The full apex.env object (if available), containing Oracle APEX runtime environment details.

Here’s the code:

function parseApexUrl(url = window.location.href) {
    const urlObj = new URL(url);
    const pathParts = urlObj.pathname.split('/').filter(Boolean);

    // Query parameters as array of {key, value}
    const paramsArray = Array.from(urlObj.searchParams.entries()).map(
        ([key, value]) => ({ key, value })
    );

    // Determine if classic (non-friendly) URL: /ords/f?p=...
    const isClassic =
        pathParts.length > 0 &&
        pathParts[pathParts.length - 1] === 'f' &&
        urlObj.searchParams.has('p');

    // Oracle APEX environment (if available)
    const apexEnv = (typeof apex !== "undefined" && apex.env) ? apex.env : null;
    const apexSessionId = apexEnv ? apexEnv.APP_SESSION : null;
    const apexPageId = apexEnv ? apexEnv.APP_PAGE_ID : null;

    // Classic URL parsing
    let workspace = null, appAlias = null, pageAlias = null, serviceName = null, baseIndex = null;
    let sessionId = null, pageId = null;

    if (isClassic) {
        serviceName = pathParts[0] || null;
        // Extract appId, pageId/alias, sessionId from the p parameter
        const fParam = urlObj.searchParams.get('p');
        const parts = fParam ? fParam.split(':') : [];
        sessionId = apexSessionId || (parts.length > 2 ? parts[2] : urlObj.searchParams.get('session')) || null;
        if (apexPageId && parts[1]) {
            if (parts[1] === apexPageId) {
                pageId = apexPageId;
                pageAlias = null;
            } else {
                pageId = apexPageId;
                pageAlias = parts[1];
            }
        } else {
            pageId = parts[1] || null;
            pageAlias = null;
        }
    } else {
        // Friendly URL parsing
        let rIndex = pathParts.indexOf('r');
        baseIndex = (rIndex !== -1) ? rIndex + 1 : null;
        workspace = (baseIndex !== null) ? pathParts[baseIndex] || null : null;
        appAlias = (baseIndex !== null) ? pathParts[baseIndex + 1] || null : null;
        pageAlias = (baseIndex !== null) ? pathParts[baseIndex + 2] || null : null;
        serviceName = (rIndex > 0) ? pathParts.slice(0, rIndex).join('/') : (pathParts[0] || null);
        sessionId = apexSessionId || urlObj.searchParams.get('session') || null;
        pageId = apexPageId || null;
    }

    // Reconstruct the full URL
    let fullUrlReconstructed;
    if (isClassic) {
        // For classic URLs, preserve the original query string exactly
        const portPart = urlObj.port ? `:${urlObj.port}` : '';
        fullUrlReconstructed = `${urlObj.protocol}//${urlObj.hostname}${portPart}${urlObj.pathname}`;
        if (urlObj.search) {
            fullUrlReconstructed += urlObj.search;
        }
    } else {
        // For friendly URLs, reconstruct as normal
        const portPart = urlObj.port ? `:${urlObj.port}` : '';
        const reconstructedQuery = paramsArray
            .map(param => encodeURIComponent(param.key) + '=' + encodeURIComponent(param.value))
            .join('&');
        fullUrlReconstructed = `${urlObj.protocol}//${urlObj.hostname}${portPart}${urlObj.pathname}${reconstructedQuery ? '?' + reconstructedQuery : ''}`;
    }

    // Compare original and reconstructed URLs
    const reconstructionValid = (url === fullUrlReconstructed);

    return {
        protocol: urlObj.protocol,
        hostname: urlObj.hostname,
        port: urlObj.port,
        fullUrl: url,
        fullUrlReconstructed: fullUrlReconstructed,
        reconstructionValid: reconstructionValid,
        paramsArray: paramsArray,
        workspace: workspace,
        appAlias: appAlias,
        pageAlias: pageAlias,
        serviceName: serviceName,
        pathParts: pathParts,
        baseIndex: baseIndex,
        sessionId: sessionId,
        pageId: pageId,
        apexEnv: apexEnv
    };
}

Run it with

parseApexUrl()

Example output

{
    "protocol": "https:",
    "hostname": "apex.oracle.com",
    "port": "",
    "fullUrl": "https://apex.oracle.com/pls/apex/r/x/employees/employee?p5_empno=7499&session=10815119570851&cs=3irSp6x",
    "fullUrlReconstructed": "https://apex.oracle.com/pls/apex/r/x/employees/employee?p5_empno=7499&session=10815119570851&cs=3irSp6x",
    "reconstructionValid": true,
    "paramsArray": [
        {
            "key": "p5_empno",
            "value": "7499"
        },
        {
            "key": "session",
            "value": "10815119570851"
        },
        {
            "key": "cs",
            "value": "3irSp6x"
        }
    ],
    "workspace": "x",
    "appAlias": "employees",
    "pageAlias": "employee",
    "serviceName": "pls/apex",
    "pathParts": [
        "pls",
        "apex",
        "r",
        "x",
        "employees",
        "employee"
    ],
    "baseIndex": 3,
    "sessionId": "10815119570851",
    "pageId": "5",
    "apexEnv": {
        "APP_USER": "MATT@EXAMPLE.COM",
        "APP_ID": "243414",
        "APP_PAGE_ID": "5",
        "APP_SESSION": "10815119570851",
        "APP_FILES": "r/x/243414/files/static/v6/",
        "WORKSPACE_FILES": "r/x/files/static/v21/",
        "APEX_VERSION": "24.2.6",
        "APEX_BASE_VERSION": "24.2",
        "COMPATIBILITY_MODE": 21.2,
        "NONCE": "S5VE33y8QiDlH7eWqLzF_A",
        "APEX_FILES": "https://static.oracle.com/cdn/apex/24.2.6/"
    }
}

Or for something specific, just use dot-notation

parseApexUrl().serviceName
// pls/apex

Of if you want something more specific from it, as AI to convert it for you

Take this script below,  can you give me the simpliest form (feweest lines of still readable code) 
of returning serviceName

[PASTE ABOVE CODE HERE]

Results in

function getServiceName(url = window.location.href) {
  const pathParts = new URL(url).pathname.split('/').filter(Boolean);
  const rIndex = pathParts.indexOf('r');
  return rIndex > 0 ? pathParts.slice(0, rIndex).join('/') : pathParts[0] || null;
}

ENJOY!

Whats’ the picture? Lambs at Kirkby Overblow - Visit Yorkshire!

0
Subscribe to my newsletter

Read articles from Matt Mulvaney directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Matt Mulvaney
Matt Mulvaney

With around 20 years on the job, Matt is one of the most experienced software developers at Pretius. He likes meeting new people, traveling to conferences, and working on different projects. He’s also a big sports fan (regularly watches Leeds United, Formula 1, and boxing), and not just as a spectator – he often starts his days on a mountain bike, to tune his mind.