Featured Answer:
IBM AS/400 (iSeries) applications accessed via TN5250 green-screen remain critical in IT, finance, and government. Browser automation helps automate inventory and order data pulls, transaction posting workflows, and nightly exports and reconciliations through web-based TN5250 emulators.
Table of Contents
- Introduction
- Why Use Browser Automation for IBM AS/400 (iSeries)?
- Setting Up IBM AS/400 (iSeries) Automation
- Automating Inventory and Order Data Pulls
- Automating Transaction Posting Workflows
- Running Nightly Exports and Reconciliations
- Exporting AS/400 Data for External Systems
- Research and Data Extraction
- Handling AS/400 (TN5250) Screens and Function Keys
- Syncing with External Systems
- Best Practices
- Resources
- Conclusion
Introduction
IBM AS/400 (iSeries, now IBM i) applications accessed via TN5250 green-screen terminal emulation remain critical in IT, finance, and government—powering ERP, inventory, order management, and transaction systems. Many of these applications have no APIs or only limited host integration options. Organizations increasingly use web-based TN5250 emulators (HTML5 5250, web-to-host gateways) to access AS/400 sessions from a browser. Browser automation provides a reliable solution to automate inventory and order data pulls, automate transaction posting workflows, and run nightly exports and reconciliations directly through the AS/400 web interface, enabling streamlined operations without costly host rewrites.
Why Use Browser Automation for IBM AS/400 (iSeries)?
- No or Limited APIs: Legacy AS/400 applications often have no APIs; TN5250 screen automation is the only integration path
- Inventory and Order Data: Automate pulling inventory levels, order status, shipments, and stock reports from green-screen menus
- Transaction Posting: Automate posting workflows (sales orders, invoices, journal entries, receipts) into AS/400 transactions
- Nightly Exports: Run scheduled exports and reconciliations without manual green-screen sessions
- Research and Reporting: Pull AS/400 data for research, analytics, and regulatory reporting
- Reconciliation: Extract and reconcile AS/400 data with ERP, accounting, or warehouse systems
- Cost Avoidance: Avoid expensive host integration projects, ETL tools, or custom middleware
- Web-to-Host Access: Many organizations already use browser-based TN5250; automation leverages existing access
Setting Up IBM AS/400 (iSeries) Automation
Connect to your web-based TN5250 session (HTML5 emulator, web-to-host gateway, or similar) and automate AS/400 green-screen workflows:
import { chromium } from 'playwright';
const response = await fetch("https://api.anchorbrowser.io/api/sessions", {
method: "POST",
headers: {
"anchor-api-key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
'headless': false,
'proxy': { 'type': 'residential', 'country': 'US' }
}),
});
const { id } = await response.json();
const connectionString = `wss://connect.anchorbrowser.io?apiKey=YOUR_API_KEY&sessionId=${id}`;
const browser = await chromium.connectOverCDP(connectionString);
const context = browser.contexts()[0];
const ai = context.serviceWorkers()[0];
const page = context.pages()[0];
await page.goto("https://as400.yourorg.com/tn5250");
await ai.evaluate(JSON.stringify({
prompt: 'Log in to the AS/400 (iSeries) TN5250 session using the provided credentials. Enter user ID and password at the sign-on screen. Press Enter to reach the main menu.'
}));
Automating Inventory and Order Data Pulls
Extract inventory levels, order status, shipments, and stock data from AS/400 green-screen menus:
const extractScreenData = async (page, ai, config) => {
const { menuPath, fields } = config;
await ai.evaluate(JSON.stringify({
prompt: `Navigate through AS/400 menu: ${menuPath || 'current screen'}. Use Enter, Tab, or F keys as needed.`
}));
await page.waitForTimeout(500);
const screenText = await page.locator('pre, .terminal-screen, [role="log"]').first().textContent().catch(() => null);
const extracted = await ai.evaluate(JSON.stringify({
prompt: `Parse this AS/400 screen and extract: ${fields?.join(', ') || 'all visible data'}. Return as JSON.`
})).catch(() => null);
return extracted ? JSON.parse(extracted) : { raw: screenText };
};
const extractReportScreens = async (page, ai, reportParams) => {
const { reportMenu, dateRange, maxPages } = reportParams;
await ai.evaluate(JSON.stringify({
prompt: `Navigate to report: ${reportMenu}. Set date ${dateRange?.start || 'start'} to ${dateRange?.end || 'end'}. Run.`
}));
const rows = [];
let pageNum = 0;
while (pageNum < (maxPages || 100)) {
const screenData = await extractScreenData(page, ai, { fields: ['all rows'] });
if (screenData?.rows) rows.push(...screenData.rows);
const hasMore = await ai.evaluate(JSON.stringify({
prompt: 'Is there a next page (F8)? If yes, press it. If no, return false.'
}));
if (!hasMore) break;
pageNum++; await page.waitForTimeout(300);
}
return rows;
};
const pullInventoryData = async (page, ai, config) => {
const { warehouse, itemRange } = config;
await ai.evaluate(JSON.stringify({
prompt: 'Navigate to the Inventory or Stock Inquiry menu in AS/400. Use the menu path or command (e.g., WRKINV, DSPINV, or your inventory program).'
}));
await ai.evaluate(JSON.stringify({
prompt: `Enter warehouse/location ${warehouse || 'all'} and item range ${itemRange || 'all'}. Display inventory levels. Press Enter.`
}));
await page.waitForTimeout(500);
const screenText = await page.locator('pre, .terminal-screen, [role="log"]').first().textContent().catch(() => null);
const extracted = await ai.evaluate(JSON.stringify({
prompt: `Parse this AS/400 inventory screen and extract: item number, description, quantity on hand, quantity committed, reorder point, warehouse. Return as JSON array of records.`
})).catch(() => null);
return extracted ? JSON.parse(extracted) : { raw: screenText };
};
const pullOrderData = async (page, ai, orderParams) => {
const { orderType, dateRange, status } = orderParams;
await ai.evaluate(JSON.stringify({
prompt: 'Navigate to the Order Inquiry or Order Management menu in AS/400 (e.g., WRKORD, DSPORD, or your order program).'
}));
await ai.evaluate(JSON.stringify({
prompt: `Set order type ${orderType || 'all'}, date range ${dateRange?.start || 'start'} to ${dateRange?.end || 'end'}, status ${status || 'all'}. Display orders. Press Enter.`
}));
const rows = [];
let pageNum = 0;
while (pageNum < 100) {
const screenData = await extractScreenData(page, ai, { fields: ['order number', 'customer', 'date', 'status', 'amount'] });
if (screenData?.rows) rows.push(...screenData.rows);
const hasMore = await ai.evaluate(JSON.stringify({
prompt: 'Is there a next page (e.g., F8 or bottom option)? If yes, press it. If no, return false.'
}));
if (!hasMore) break;
pageNum++;
await page.waitForTimeout(300);
}
return rows;
};
Automating Transaction Posting Workflows
Post transactions (sales orders, invoices, journal entries, receipts) into AS/400 screens in batch:
const postTransactions = async (page, ai, transactions) => {
const results = [];
for (const txn of transactions) {
await ai.evaluate(JSON.stringify({
prompt: 'Navigate to the transaction entry screen (e.g., sales order entry, invoice entry, journal entry, or your posting program). Ensure we are on a clean input screen.'
}));
await ai.evaluate(JSON.stringify({
prompt: `Fill in the transaction form with: ${JSON.stringify(txn)}. Tab to each field and enter the value. Use the correct format (dates, amounts, account codes) for AS/400 fields.`
}));
await ai.evaluate(JSON.stringify({
prompt: 'Submit the transaction (press Enter or F6/F14 for Post). Wait for confirmation or error screen.'
}));
await page.waitForTimeout(400);
const result = await ai.evaluate(JSON.stringify({
prompt: 'Read the result screen. Extract: success/error status, document or reference number if shown, and any error messages. Return as JSON { status, refId, message }.'
})).catch(() => null);
results.push(result ? JSON.parse(result) : { status: 'unknown' });
if (result?.status === 'error') {
await ai.evaluate(JSON.stringify({
prompt: 'Navigate back to the main menu or transaction entry screen for the next record.'
}));
}
}
return results;
};
Running Nightly Exports and Reconciliations
Schedule and run nightly exports and reconciliations from AS/400:
const runNightlyExport = async (page, ai, exportConfig) => {
const { reportMenu, dateRange, outputPath } = exportConfig;
await ai.evaluate(JSON.stringify({
prompt: `Navigate to the report or export menu: ${reportMenu}. Set date range ${dateRange?.start || 'yesterday'} to ${dateRange?.end || 'yesterday'}. Run the report.`
}));
const rows = await extractReportScreens(page, ai, { reportMenu, dateRange });
const fs = await import('fs');
fs.writeFileSync(outputPath, JSON.stringify(rows, null, 2));
return { records: rows.length, path: outputPath };
};
const runNightlyReconciliation = async (page, ai, reconcileConfig) => {
const { as400Report, targetDataUrl, keyFields } = reconcileConfig;
const as400Data = await runNightlyExport(page, ai, { reportMenu: as400Report.report, dateRange: as400Report.dateRange, outputPath: '/tmp/as400_export.json' });
const as400Records = JSON.parse(await import('fs').then(fs => fs.readFileSync(as400Data.path, 'utf8')));
const response = await fetch(targetDataUrl);
const targetRecords = await response.json();
const reconciled = reconcile(as400Records, targetRecords, keyFields);
return { as400Count: as400Records.length, targetCount: targetRecords.length, reconciled };
};
Exporting AS/400 Data for External Systems
Extract AS/400 data in a format ready for ERP, accounting, or data warehouses:
const exportAS400Data = async (page, ai, exportParams) => {
const { screenPath, outputFormat, dateRange } = exportParams;
await ai.evaluate(JSON.stringify({
prompt: `Navigate to ${screenPath} in AS/400. Set date range ${dateRange?.start || 'N/A'} to ${dateRange?.end || 'N/A'} if applicable. Display or run the report.`
}));
const data = await extractScreenData(page, ai, { fields: ['all'] });
if (outputFormat === 'csv') {
return arrayToCSV(data?.rows || [data]);
}
return JSON.stringify(data, null, 2);
};
Research and Data Extraction
Pull AS/400 data for research, analytics, and regulatory reporting:
const extractDataForResearch = async (page, ai, researchParams) => {
const { reportType, filters, outputPath } = researchParams;
await ai.evaluate(JSON.stringify({
prompt: `Navigate to the AS/400 report or query: ${reportType}. Apply filters: ${JSON.stringify(filters)}. Run the report.`
}));
const allData = await extractReportScreens(page, ai, { reportMenu: reportType, dateRange: filters?.dateRange });
const fs = await import('fs');
fs.writeFileSync(outputPath, JSON.stringify(allData, null, 2));
return { records: allData.length, path: outputPath };
};
Handling AS/400 (TN5250) Screens and Function Keys
Work with 5250-specific behavior: function keys (F3=F12, F13=F24), Enter, and screen navigation:
const sendFunctionKey = async (page, fKey) => {
await page.keyboard.press(`F${fKey}`);
await page.waitForTimeout(300);
};
const navigateAS400Menu = async (page, ai, menuOptions) => {
for (const option of menuOptions) {
await ai.evaluate(JSON.stringify({
prompt: `On the current AS/400 screen, select or type the option for: ${option}. Press Enter. Wait for the next screen.`
}));
await page.waitForTimeout(400);
}
};
Syncing with External Systems
Export AS/400 data for integration with ERP, accounting, or warehouses:
const syncToExternalSystem = async (page, ai, config) => {
const { as400Screen, dateRange, targetUrl } = config;
const records = await extractReportScreens(page, ai, { reportMenu: as400Screen, dateRange });
const response = await fetch(targetUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ records })
});
return { synced: records.length, status: response.status };
};
Best Practices
- Security: Use secure credential storage; AS/400 IDs often have elevated access—restrict automation credentials
- Screen Stability: AS/400 screens can vary by application; add waits and validate screen content before extracting
- Field Mapping: AS/400 field positions can change; prefer label-based extraction over fixed coordinates
- Batch Throttling: Add delays between transactions to avoid overloading the host or triggering record locks
- Nightly Timing: Schedule exports during low-usage windows to avoid contention with users
- Error Recovery: Handle session drops, "device not available," and host-unavailable errors with retries
- Data Validation: Validate extracted data before syncing; AS/400 formats (EBCDIC, packed, zoned) differ from modern systems
- Reconciliation Audit: Log export and reconciliation results for compliance and dispute resolution
- Session Timeout: AS/400 sessions timeout; implement re-login and resume logic for long-running nightly jobs
Resources
- Anchor Browser Documentation - Complete API reference and guides
- Anchor Browser Playground - Try browser automation in your browser
Conclusion
Browser automation provides a flexible and cost-effective alternative to AS/400 APIs and heavy host integration for IBM AS/400 (iSeries) green-screen applications. By leveraging intelligent browser agents against web-based TN5250 emulators, you can automate inventory and order data pulls, automate transaction posting workflows, and run nightly exports and reconciliations—workflows that traditionally required custom middleware or manual green-screen sessions. Whether you need to pull inventory for warehouses, post transactions to the general ledger, or run nightly reconciliations, browser automation enables efficient operations for organizations running IBM AS/400 (iSeries) applications.
Start automating your AS/400 (iSeries) workflows today and streamline inventory, posting, and exports!