VERSICH

Read NetSuite Country Codes in SuiteScript Without Mapping Errors

read netsuite country codes in suitescript without mapping errors

When a SuiteScript automation needs a country, the difficult part is not reading one field. The difficult part is understanding whether NetSuite is returning a country name, an ISO-style code, or a record identifier. Using the wrong representation can create failed searches, incorrect integrations, and country values that appear valid but cannot be saved.

NetSuite country codes in SuiteScript are generally retrieved from a record’s country field with `getValue()` or `getText()`. Use `getValue()` when you need the stored value for comparisons or updates, and use `getText()` when you need the readable country name. Do not assume that the value is a numeric internal ID. For a complete country list, use a supported country search or SuiteQL query only after confirming the available country fields in your account’s Records Catalog.

That distinction is the central answer to how to get NetSuite country names and internal IDs with SuiteScript. A customer, vendor, address, sales order, or subsidiary record can expose country information through a select field, but the returned value depends on the API method you call. Our approach is to identify the source record, inspect the field behavior, choose the representation required by the downstream process, and test the result in the target account.

What does NetSuite return for a country field?

NetSuite country fields are select fields backed by country data, but their stored values are not always presented like ordinary numeric record IDs. In many common record contexts, the value is an ISO-style country code such as `US`, while the displayed text is a name such as `United States`.

The exact result depends on the record type, field, account configuration, and SuiteScript API method. A script should therefore treat these as different values:

Value typeExampleBest use
Stored field value`US`Comparisons, filters, updates, integration mapping
Display text`United States`User-facing output, emails, reports
Record identifierAccount-specific identifier, where exposedDirect reference to a country record or search result
External code`US`, `GB`, or another partner codeCross-system integration

The important implementation detail is that `getValue()` and `getText()` do not answer the same question. `getValue()` returns the stored value. `getText()` returns the label NetSuite displays for the selected value. If a script needs to send a country to an external application, the stored code is usually more reliable than the display name because names can vary by language or formatting.

This is also why copying a value from the user interface and assuming it is an internal ID creates problems. NetSuite may display “United Kingdom” while the field value is `GB`. In another context, a country record search might expose a separate identifier. Those values should not be treated as interchangeable.

How do you get a NetSuite country name with SuiteScript?

Use `getText()` on the relevant country field when the script needs the readable country name. Use `getValue()` alongside it when the process also needs the stored country value.

The following SuiteScript 2.1 example reads the billing country from a loaded customer record:

/**
 * @NApiVersion 2.1
 */
define(['N/record'], (record) => {
    const getCustomerCountry = (customerId) => {
        const customer = record.load({
            type: record.Type.CUSTOMER,
            id: customerId,
            isDynamic: false
        });

        return {
            value: customer.getValue({
                fieldId: 'billcountry'
            }),
            text: customer.getText({
                fieldId: 'billcountry'
            })
        };
    };

    return {
        getCustomerCountry
    };
});

A result might resemble:

{
    value: 'US',
    text: 'United States'
}

The actual output should be inspected in the account where the script runs. Avoid hard-coding the example result as a universal rule.

For a customer record, `billcountry` is the billing country field and `shipcountry` is commonly used for the shipping country. Other record types use different field IDs. A transaction might expose billing and shipping address fields directly, while a custom record might contain a custom select field such as `custrecord_country`.

If the script is running against the current record, `N/currentRecord` provides the same general distinction:

/**
 * @NApiVersion 2.1
 */
define(['N/currentRecord'], (currentRecord) => {
    const readCountry = () => {
        const current = currentRecord.get();

        return {
            value: current.getValue({
                fieldId: 'shipcountry'
            }),
            text: current.getText({
                fieldId: 'shipcountry'
            })
        };
    };

    return {
        readCountry
    };
});

`N/currentRecord` is appropriate for client scripts and interactive pages. It does not replace `N/record` in server-side scripts such as scheduled scripts, map/reduce scripts, or user event scripts.

How do you get a NetSuite country internal ID?

The answer depends on what “internal ID” means in the process. If the country field itself returns a stored code, that code is the value NetSuite expects for that field. It is not necessarily a numeric ID that should be converted or looked up.

For example, this comparison is appropriate when the field stores a country code:

const countryValue = customer.getValue({
    fieldId: 'billcountry'
});

if (countryValue === 'US') {
    // Apply United States-specific logic.
}

This comparison is less reliable:

if (countryText === 'United States') {
    // Avoid using display text as the primary key.
}

Display text is intended for presentation. It can be affected by language, capitalization, translation, or account-specific labels. A stable stored value is generally better for business logic.

When a downstream system specifically requires a numeric country identifier, first confirm that the target field expects a country record reference rather than a country code. The Records Catalog and SuiteScript Records Browser are the right places to verify the field type and supported values. Do not convert `US` into an invented number, and do not assume the identifier is portable between accounts.

This matters in sandbox refreshes, account migrations, and multi-account deployments. NetSuite internal IDs are account-specific. A value that identifies a record in one account is not automatically the same record in another account. Our guidance on why NetSuite internal IDs should not be assumed across accounts applies to country-related lookups as well as custom records and configuration records.

How can you retrieve a full list of NetSuite countries?

For a complete list, use a country search or SuiteQL only after confirming that the country record and its fields are exposed in your account and script context. NetSuite account features and API availability affect which search types and columns are available.

A supported `N/search` country search may look like this:

/**
 * @NApiVersion 2.1
 */
define(['N/search'], (search) => {
    const getCountries = () => {
        const countrySearch = search.create({
            type: 'country',
            columns: [
                search.createColumn({
                    name: 'internalid',
                    sort: search.Sort.ASC
                }),
                search.createColumn({
                    name: 'name'
                })
            ]
        });

        const countries = [];

        countrySearch.run().each((result) => {
            countries.push({
                id: result.getValue({
                    name: 'internalid'
                }),
                name: result.getValue({
                    name: 'name'
                })
            });

            return true;
        });

        return countries;
    };

    return {
        getCountries
    };
});

Do not deploy this pattern without validating the search type and columns in the account. The Records Catalog provides the current schema available to your account and is more authoritative than an old code sample. If `country` is not available as a search type, the script should use the country value already present on the source record or use a maintained mapping that has been verified against the account.

A search result also introduces a separate question: does the returned `id` represent the value expected by the field you want to set? Before using it in `setValue()`, test the target field with a non-production record. A country search result identifier and a country select field value are not automatically interchangeable.

For scripts that need a country list repeatedly, caching is also important. A map/reduce or scheduled script should not run the same country lookup for every transaction when the list is stable. Load the reference data once per execution where practical, or maintain a controlled mapping in a custom record when business-specific values are required.

What is the difference between getValue() and getText()?

`getValue()` returns the field’s stored value, while `getText()` returns the field’s displayed label. That distinction applies to country fields and many other NetSuite select fields.

SuiteScript methodReturnsUse it for
`getValue()`Stored country valueComparisons, filters, updates, integration payloads
`getText()`Displayed country labelUser interfaces, logs, notifications
`setValue()`Writes a stored valueSetting a verified code or field value
`setText()`Selects by displayed textControlled user-facing values, with validation

When setting a country, prefer the method that matches the verified field behavior:

customer.setValue({
    fieldId: 'billcountry',
    value: 'US'
});

Or, where the field supports text selection and the label is controlled:

customer.setText({
    fieldId: 'billcountry',
    text: 'United States'
});

`setText()` is more vulnerable to label differences. If the account uses translated labels or the value has been customized, the same text may not resolve as expected. `setValue()` is generally preferable for integration and automation because it avoids matching against presentation text.

A common error occurs when a developer calls `getText()` and then passes the result into `setValue()`. The source returns `United States`, while the destination expects `US`. The script then fails validation or saves the wrong value. Keep the stored value and display text in separate variables with explicit names.

How should SuiteScript handle country values in integrations?

Integration logic should normalize country data at the boundary between NetSuite and the external system. Do not let every script, workflow, and connector invent its own country mapping.

A practical payload might preserve both representations:

const country = {
    netsuiteValue: customer.getValue({
        fieldId: 'shipcountry'
    }),
    netsuiteName: customer.getText({
        fieldId: 'shipcountry'
    })
};

const payload = {
    countryCode: country.netsuiteValue,
    countryName: country.netsuiteName
};

The external application may require ISO 3166-1 alpha-2 codes, alpha-3 codes, numeric codes, or its own country key. The mapping should be explicit. If the partner expects `USA` while NetSuite returns `US`, translate that value in one controlled integration layer instead of scattering conversions across user events and client scripts.

A durable integration also records how unmatched values are handled. The script should log the source value, target system, and mapping status, then stop or route the record for review when the country is unknown. Silently sending a blank country is a data-quality problem that becomes difficult to trace later.

For larger integrations, country handling belongs in the integration architecture rather than inside a single transaction script. Our NetSuite integration platform services cover SuiteScript integrations alongside REST and SOAP-based data exchange. This is especially relevant when country values move between NetSuite, ecommerce, CRM, tax, shipping, and fulfillment systems.

Common country lookup errors in SuiteScript

The most frequent failure is assuming every country reference is a numeric internal ID. NetSuite field values must be confirmed from the actual field definition and runtime output.

Other common errors include:

  • Comparing `getText()` output when the business rule should use the stored code.

  • Calling `getValue()` on a field that is not present on the selected record type.

  • Using `billcountry` when the process requires `shipcountry`.

  • Passing a display name to `setValue()`.

  • Assuming a country value is portable between NetSuite accounts.

  • Running a search with unsupported country columns.

  • Building a new country mapping without documenting unknown-value behavior.

  • Reading sublist address data without confirming the sublist and line index.

Address sublists deserve particular attention. If the country belongs to a customer address rather than the main customer body, the script must read the address subrecord or address sublist correctly. SuiteScript sublist indexes are zero-based, and a displayed line number is not always the same as the index used by the record API. Our explanation of NetSuite line references and sublist indexes covers that distinction in detail.

A practical testing process for country fields

Country logic should be tested with more than one familiar country. Use records with different billing and shipping countries, blank values, and addresses stored in subrecords. Also test the same script role and deployment context used in production, because permissions and execution context affect what the script can read.

Before deploying, verify the following:

  1. Identify the exact record type and field ID.

  2. Log both `getValue()` and `getText()` in a non-production account.

  3. Confirm whether the target field expects a code, label, or record reference.

  4. Test blank, invalid, and unexpected country values.

  5. Confirm integration mappings against the receiving system’s specification.

  6. Re-test after a sandbox refresh or account migration if identifiers are involved.

Use governance carefully in batch scripts. Loading every customer record solely to read one country field is expensive. A saved search, search result, or SuiteQL query may be more efficient when the process needs many records. The right option depends on whether the script needs record behavior, display text, joins, subrecord data, or only a small set of stored values.

Conclusion

Getting NetSuite country names and internal values with SuiteScript starts with identifying what the field actually stores. Use `getValue()` for the stored country value, `getText()` for the displayed name, and never assume that a country code is a numeric internal ID. When a complete country list or external mapping is required, validate the available search schema, account for account-specific identifiers, and keep integration conversions in one controlled layer.

For help designing reliable SuiteScript lookups, country mappings, or broader NetSuite data integrations, contact Versich to discuss your requirements.

Looking for NetSuite Solutions?

Explore our expert NetSuite services and get started today.

Get Started
CTA Illustration

Frequently Asked Questions

How do I get the country name in SuiteScript?

Use `getText()` on the relevant country field, such as `billcountry` or `shipcountry`. For example, `record.getText({ fieldId: 'billcountry' })` returns the displayed country name when the field is available on the loaded record.

How do I get a country code in NetSuite SuiteScript?

Use `getValue()` on the country field and inspect the result in your account. In common record contexts, NetSuite returns an ISO-style value such as `US`, but the exact field behavior should be confirmed before deployment.

Is a NetSuite country internal ID the same as a country code?

Not necessarily. A country field may store an ISO-style code, while a country search may expose a separate record identifier. Confirm the field definition and supported values in the Records Catalog instead of converting or assuming identifiers.

Should I use `getValue()` or `getText()` for a country field?

Use `getValue()` for business logic, comparisons, updates, and integration payloads when the stored value is the required representation. Use `getText()` for readable output such as labels, emails, logs, and user-facing pages.

Can I search all countries with SuiteScript?

You can use a supported country search or SuiteQL query if your account exposes the country record and required fields. Validate the search type and columns in the Records Catalog, and confirm that any returned identifier is compatible with the field you plan to set.

How much does it cost to add a country lookup to SuiteScript?

The cost depends on whether the requirement is a small field-level change, a reusable country mapping, or a broader integration involving multiple systems and exception handling. A precise estimate requires reviewing the record types, deployment contexts, mappings, testing needs, and volume.

Is a country mapping required for NetSuite integrations?

A mapping is required whenever the external system uses a different country representation than NetSuite. If both systems use the same verified code, a direct pass-through may be sufficient, but the integration should still define how blank and unsupported values are handled.